Framework应用和解析(三)

这一次分享一下BeeMessage, BeeModel, 和BeeUISignal。这三个东东就是Controller, Model, 和Event的主要实现。您也可以到Bee的/documents/developer_manual.pdf中查看详细的开发手册,希望您看了这篇文章能对这几个组件理解更深,适合干什么,从而更得心应手得使用。本文试图解答几个问题:

A1:BeeMessage就是对网络数据请求的封装,也就是常说的“协议”。BeeMessage和BeeHttpRequest(ASIDataFormRequest的封装)协同工作,通过内置的多个状态更新同步BeeHttpRequest的状态。包括发送和接收请求,解析数据,将数据发送给感兴趣的上层对象(UI或Model)。BeeMessage和BeeHttpRequest都持有responder数据成员,其中BeeHttpRequest的Responder就是对应的BeeMessage, BeeMessage对应的Responder就是对BeeMessage感兴趣的UI或者Model。看下图:

可以看到,UIResponder将创建BeeMessage,填入Http参数,并将自己传入做为Responder。BeeMessage将自己传入BeeHttpRequest。UIResponder通过BeeMessage提供的Block来检查BeeMessage的状态。BeeMessage和BeeHttpRequest都实现为6个子状态,表示Http请求的状态流转并同步。这些状态流转都在BeeMessage的routine函数里完成。来看看UIResponder,和BeeMessage routine的代码:

UIResponder:-(void) getNewsList {BeeMesage * api = [API_NEWS_LIST api]; //加入Http参数 api.INPUT( @"uid", [NSString stringWithFormat:@"%d", _uid]);<p style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; font-family: Menlo;"></p> api.whenUpdate = ^{if ( api.sending ){//处理发送}else if(api.succeed){//发送成功,获得BeeMessage解析好的数据[self.news addObjectsFromArray:api.resp.news];}else if ( api.failed ){//处理失败}else if ( api.cancelled ){//处理取消}};[api send];}

BeeMessage routine函数:- (void)routine{if ( self.sending ){NSString * requestURI = [[[ServerConfig sharedInstance] url] stringByAppendingString:api_news_list];self.HTTP_GET( requestURI );}else if ( self.succeed ){NSError* error;//通过XML解析回文CXMLDocument * document = [[CXMLDocument alloc] initWithXMLString:self.responseString options:NSUTF8StringEncoding error:&error];NSArray* newslist = [document nodesForXPath:@"oschina/newslist/news" error:&error];for ( CXMLElement* newsXML in newslist ){if(newsXML == nil) continue;NEWS* news = [NEWS createByXML:newsXML];[self.resp.news addObject:news];}if ( nil == self.resp || NO == [self.resp validate] ){self.failed = YES;return;}}else if ( self.failed ){}else if ( self.cancelled ){}}@end

以上是BeeMessage的工作流程。BeeMessage的优点是大幅简化了数据协议的编写,省略了delegate, 散落在代码各处的block,,让代码好维护。BeeHttpRequest封装了JSON kit, 可以非常容易得将回文转换为嵌套字典, XML则需要自己写parser。在实际的App中往往编写几十条这样的BeeMessage是十分枯燥,Bee在/Tools/Scaffold中提供自动化生成BeeMessage代码的工具,支持JSON数据。

A2:BeeModel是本地数据存储的基类,附带了观察者支持。BeeModel的观察者一般来说是UI, 持有这个BeeModel, 比如说上面的新闻列表数据,UI是新闻列表展示的ViewController。BeeModel需要开发者在子类中自己实现本地存储,函数是saveCache, loadCache。Bee实现了基于plist的BeeUserDefaults, 实现了基于文件的BeeFileCache, 实现了基于内存字典或数组的BeeMemCache, BeeImageCache, 可以根据需求灵活使用。也可以在BeeModel里使用BeeDatabase和BeeActiveRecord, 支持本地数据库存储,具体方法参见开发者手册。

BeeModel为什么引入观察者?当然还是为了能简化delegate和notification, 从代码里看感觉应该是为BeeUISignal做铺垫。BeeUISignal的路由方式底层用反射实现,对BeeModel来说,其观察者的NSClass可以存入到缓存里,路由事件时先去缓存寻找这些观察者是否实现了事件的接收方法并优先发送,如此可以加快事件路由的效率。

BeeModel只是数据模型的基类,可以封装一个NSMutableArray,由NSMutableArray存储具体的数据对象。Core data个人认为只是SQLLite的封装,用于处理数据关联的情景。Apple大概在2004年引入Core data到OS X, 并移植到iOS, 似乎并不是很受开发者的欢迎。BeeModel处理本地存储比较灵活,提供了便利的UISignal事件,比较实用。具体使用时可以使用支持BeeUISignal的BeeViewModel。

BeeViewModel包含若干子类,主要是对几种典型的UI展现方式抽象。BeeOnceViewModel一次展示数据,BeePageViewModel支持翻页管理,BeeStreamViewModel支持瀑布式页面管理,使用很方便。比如BeeStreamViewModel, 只用实现firstPage, 和nextPage两个方法,并在Model数据更新的时候发送事件到UIViewController即可。代码如下:

– (void)firstPage{_pages = 0;[API_POST_LIST cancel];API_POST_LIST *api = [API_POST_LIST api];   //每页20个api.INPUT( @"pageIndex", @"0" );api.INPUT( @"pageSize", @"20" );api.whenUpdate = ^{@normalize( api );if ( api.sending ){[self sendUISignal:self.RELOADING];}else if ( api.succeed ){//第一页拉取成功[self.posts removeAllObjects];[self.posts addObjectsFromArray:api.resp.posts];self.loaded = YES;self.pages = 1;[self sendUISignal:self.RELOADED];}else if ( api.failed ){[self sendUISignal:self.RELOADED];}};[api send];}- (void)nextPage{[API_POST_LIST cancel];API_POST_LIST *api = [API_POST_LIST api];int curBegin = self.pages * 20;int curEnd = curBegin + 20;api.INPUT( @"pageIndex", [NSString stringWithFormat:@"%d", curBegin]);api.INPUT( @"pageSize", [NSString stringWithFormat:@"%d", curEnd] );api.whenUpdate = ^{@normalize( api );if ( api.sending ){[self sendUISignal:self.RELOADING];}else if ( api.succeed ){//处理下一页if( _pages == 0){[self.posts removeAllObjects];}[self.posts addObjectsFromArray:api.resp.posts];self.loaded = YES;self.pages = self.pages + 1;[self sendUISignal:self.RELOADED];}else if ( api.failed ){[self sendUISignal:self.FAILED];}else if ( api.cancelled ){[self sendUISignal:self.CANCELLED];}};[api send];}

很简单就完成了瀑布式分页的流程,不是吗?合适的时候发送 RELOADING和RELOADED事件给UI, UI更新界面就可以了。

A3: BeeUISignal是Bee实现的UI事件,主要有以下的特点:

便是不再存在着任何我曾经对你有过的希望。

Framework应用和解析(三)

相关文章:

你感兴趣的文章:

标签云: