这两天死了不少人,南北呼应。厦门的兄弟们别挤brt了,公交有风险,挤车需谨慎!
继续介绍Bee的mvc,框架中已经为MVC做了一定程度的封装,我们查看Bee的源码会发现对应着BeeController、BeeModel以及各种常用的View和ViewController,另外ViewLayout添加了View界面布局的灵活性,从v0.3.0版本开始更是加入了基于XML的UI模板模块。
还是先上个例子比较直观些。
这个例子,通过访问国家气象局天气预报JSON数据接口,http://www.weather.com.cn/data/sk/101010100.html,返回天气数据。
看下目录结构
把MVC分离出来放到不同的目录下。
Model层代码:
Java代码
- //
- // WeatherModel.h
- // BeeFrameWorkTest
- //
- // Created by he songhang on 13-6-8.
- // Copyright (c) 2013年 he songhang. All rights reserved.
- //
- #import <BeeFramework/Bee.h>
- @interface Weather : BeeActiveRecord
- @property(nonatomic,strong) NSString *city;//城市
- @property(nonatomic,strong) NSString *temp;//气温
- @property(nonatomic,strong) NSString *WD;//风向
- @property(nonatomic,strong) NSString *WS;//风力
- @property(nonatomic,strong) NSString *time;//发布时间
- @end
- @interface WeatherModel : BeeModel
- @property(nonatomic,strong) Weather *weather;
- -(void)loadOnline;//查询天气
- -(void)loadCache;//读取历史记录
- @end
Java代码
- //
- // WeatherModel.m
- // BeeFrameWorkTest
- //
- // Created by he songhang on 13-6-8.
- // Copyright (c) 2013年 he songhang. All rights reserved.
- //
- #import "WeatherModel.h"
- #import "WeatherController.h"
- @implementation Weather
- +(void)mapRelation{
- [super mapPropertyAsKey:@"city"];
- [super mapRelation];
- }
- @end
- @interface WeatherModel (private)
- - (void)saveCache;
- - (void)asyncSaveCache;
- @end
- @implementation WeatherModel
- -(void)loadOnline{
- [self sendMessage:WeatherController.LOAD_WEATHER];
- }
- -(void)loadCache{
- int count = Weather.DB.WHERE(@"city",@"北京").COUNT().resultCount;
- if (count>0) {
- self.weather = [Weather.DB.WHERE(@"city",@"北京").GET_RECORDS() lastObject];
- }
- }
- - (void)saveCache
- {
- [NSObject cancelPreviousPerformRequestsWithTarget:self];
- [self performSelector:@selector(asyncSaveCache) withObject:nil afterDelay:0.1f];
- }
- - (void)asyncSaveCache
- {
- _weather.SAVE();
- }
- - (void)handleMessage:(BeeMessage *)msg
- {
- [super handleMessage:msg];
- }
- - (void)handleWeatherController:(BeeMessage *)msg
- {
- if ( [msg is:WeatherController.LOAD_WEATHER] )
- {
- if ( msg.succeed )
- {
- NSDictionary *dict = [msg.output dictAtPath:@"result"];
- if (dict) {
- self.weather = (Weather *)[dict objectForClass:[Weather class]];
- [self saveCache];
- }
- }
- }
- [super handleMessage:msg];
- }
- @end
在.h中定义了一个Weather的实体,与天气数据对应,用到了BeeActiveRecord,这是Bee中的ORM框架,实现数据库与BeeActiveRecord的序列和反序列化。通常我们在做离线缓存时采用CoreData,bee采用的是DB的方式。感谢老郭为我们封装了原来的SQL语法,免去了封装枯燥的SQL语句。查看BeeActiveRecord的父类BeeDatabase,可以看到一些开源软件上用的很欢的以Block为参数的写法。
在.m中通过
Java代码
- [self sendMessage:WeatherController.LOAD_WEATHER];
向Weathercontroller发送了一个LOAD_WEATHER的请求,在handleWeatherController中响应BeeMessage的不同状态,并完成离线数据的保存工作
Java代码
- [self saveCache];
再上Controller的实现
Java代码
- //
- // WeatherController.h
- // BeeFrameWorkTest
- //
- // Created by he songhang on 13-6-8.
- // Copyright (c) 2013年 he songhang. All rights reserved.
- //
- #import "Bee_Controller.h"
- @interface WeatherController : BeeController
- AS_MESSAGE(LOAD_WEATHER)
- @end
Java代码
- //
- // WeatherController.m
- // BeeFrameWorkTest
- //
- // Created by he songhang on 13-6-8.
- // Copyright (c) 2013年 he songhang. All rights reserved.
- //
- #import "WeatherController.h"
- #import "JSONKit.h"
- #import <BeeFramework/Bee.h>
- @implementation WeatherController
- DEF_MESSAGE(LOAD_WEATHER)
- -(void)LOAD_WEATHER:(BeeMessage *)msg{
- if ( msg.sending )
- {
- NSString * callURL = @"http://www.weather.com.cn/data/sk/101010100.html" ;
- msg.HTTP_GET( callURL );
- }
- else if ( msg.progressed )
- {
- }
- else if ( msg.succeed )
- {
- NSDictionary * jsonData = [msg.response objectFromJSONData];
- if ( nil == jsonData )
- {
- [msg setLastError];
- return;
- }
- NSDictionary *weatherinfo = (NSDictionary *)[jsonData objectAtPath:@"weatherinfo"];
- [msg output:@"result", weatherinfo, nil];
- }
- else if ( msg.failed )
- {
- }
- else if ( msg.cancelled )
- {
- }
- }
- @end
WeatherController完成与天气预报服务器交互的工作,和UISignle类似,在.h中通过AS_MESSAGE(LOAD_WEATHER)定义了一个LOAD_WEATHER的方法声明,在.m中用DEF_MESSAGE(LOAD_WEATHER)对应,并完成LOAD_WEATHER的方法实现。在bee中网络层使用的是ASIHTTPRequest框架,至于为什么不用AFNetworking,这实际上是个人习惯的问题,虽然ASIHTTPRequest已经N久没更新过了,不过也够用了。BeeMessage中对ASIHTTPRequest做了很多工作,通过BeeRequestQueue,对post和get过程中状态的分离。
再来看view层,其实在这个例子中做真正做逻辑的是ViewController,注意它的父类为BeeUIBoard,正是这个类做了UIMessage的消息转发,还实现了ViewController生命周期中的UISignal化。
Java代码
- //
- // ViewController.h
- // BeeFrameWorkTest
- //
- // Created by he songhang on 13-6-3.
- // Copyright (c) 2013年 he songhang. All rights reserved.
- //
- #import <UIKit/UIKit.h>
- #import <BeeFramework/Bee.h>
- #import "WeatherModel.h"
- @interface ViewController : BeeUIBoard{
- __strong WeatherModel *_weatherModel;
- __weak IBOutlet UITextView *textView;
- }
- @end
Java代码
- //
- // ViewController.m
- // BeeFrameWorkTest
- //
- // Created by he songhang on 13-6-3.
- // Copyright (c) 2013年 he songhang. All rights reserved.
- //
- #import "ViewController.h"
- #import "WeatherController.h"
- @implementation ViewController
- -(void)load{
- _weatherModel = [[WeatherModel alloc]init];
- [_weatherModel addObserver:self];
- }
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // Do any additional setup after loading the view, typically from a nib.
- }
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
- }
- - (void)handleUISignal:(BeeUISignal *)signal
- {
- [super handleUISignal:signal];
- }
- - (void)handleUISignal_BeeUIBoard:(BeeUISignal *)signal
- {
- [super handleUISignal:signal];
- if ( [signal is:BeeUIBoard.CREATE_VIEWS] )
- {
- [self showNavigationBarAnimated:YES];
- [self showBarButton:UINavigationBar.BARBUTTON_RIGHT system:UIBarButtonSystemItemRefresh];
- self.title = @"天气预报";
- }
- else if ( [signal is:BeeUIBoard.DELETE_VIEWS] )
- {
- }
- else if ( [signal is:BeeUIBoard.LOAD_DATAS] )
- {
- [_weatherModel loadCache];
- [self refushTextView];
- }
- else if ( [signal is:BeeUIBoard.WILL_APPEAR] )
- {
- }
- else if ( [signal is:BeeUIBoard.DID_DISAPPEAR] )
- {
- }
- }
- - (void)handleUISignal_UINavigationBar:(BeeUISignal *)signal
- {
- if ( [signal is:UINavigationBar.BACK_BUTTON_TOUCHED] )
- {
- }
- else if ( [signal is:UINavigationBar.DONE_BUTTON_TOUCHED] )
- {
- [self loadOnline];
- }
- }
- -(void)loadOnline{
- [_weatherModel loadOnline];
- }
- -(void)refushTextView{
- if (_weatherModel.weather) {
- Weather *weather = _weatherModel.weather;
- NSString *weatherInfo = [NSString stringWithFormat:@"城市:%@\n气温:%@\n风向:%@\n风力%@\n发布时间:%@,",weather.city,weather.temp,weather.WD,weather.WS,weather.time];
- textView.text = weatherInfo;
- }
- }
- - (void)handleMessage:(BeeMessage *)msg
- {
- [super handleMessage:msg];
- }
- - (void)handleWeatherController:(BeeMessage *)msg
- {
- [super handleMessage:msg];
- if ( [msg is:WeatherController.LOAD_WEATHER] )
- {
- if ( msg.sending )
- {
- BeeUIActivityIndicatorView * indicator = [BeeUIActivityIndicatorView spawn];
- [self showBarButton:UINavigationBar.BARBUTTON_RIGHT custom:indicator];
- [indicator startAnimating];
- }
- else
- {
- [self showBarButton:UINavigationBar.BARBUTTON_RIGHT system:UIBarButtonSystemItemRefresh];
- }
- if ( msg.succeed )
- {
- [self refushTextView];
- }
- }
- }
- @end
这里应注意ViewController.m中的代码:
Java代码
- -(void)load{
- _weatherModel = [[WeatherModel alloc]init];
- [_weatherModel addObserver:self];//注意点!!!
- }
,结合WeatherModel.m中的
Java代码
- - (void)handleWeatherController:(BeeMessage *)msg
- {
- if ( [msg is:WeatherController.LOAD_WEATHER] )
- {
- if ( msg.succeed )
- {
- NSDictionary *dict = [msg.output dictAtPath:@"result"];
- if (dict) {
- self.weather = (Weather *)[dict objectForClass:[Weather class]];
- [self saveCache];
- }
- }
- }
- [super handleMessage:msg];//注意点
- }
如果把
Java代码
- [super handleMessage:msg];
去掉,那么ViewController中的handleMessage和handleWeatherController将无法响应。
本篇通过天气预报介绍了Bee中的MVC的实现场景,当然你也可以根据自己的需要选择适用的模块,你可以在Model中直接实现网络层交互,也可以去掉model层,直接在UIBoard中调用BeeController,怎么选择还是看个人习惯。
以上代码下载:https://github.com/ilikeido/BeeFrameworkTest/tree/master/lesson4