iOS快速开发框架Bee-Framework应用和解析(三) - Message, Model, Signal

转载 2016年06月01日 01:34:01

原文:http://www.itnose.net/detail/6211318.html

2015-02-14 17:40

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

        BeeMessage是如何实现的?如何做到封装Http过程的,有什么优缺点和适用场合?        BeeModel是如何实现的?和Core Data在使用上有何取舍?有哪些使用方式满足不同的需求?        BeeUISignal是如何实现的?为了满足什么需求而实现成这样?与NSNotification比较有什么优缺点和适用场合?
       A1:BeeMessage就是对网络数据请求的封装,也就是常说的“协议”。BeeMessage和BeeHttpRequest(ASIDataFormRequest的封装)协同工作,通过内置的多个状态更新同步BeeHttpRequest的状态。包括发送和接收请求,解析数据,将数据发送给感兴趣的上层对象(UI或Model)。BeeMessage和BeeHttpRequest都持有responder数据成员,其中BeeHttpRequest的Responder就是对应的BeeMessage, BeeMessage对应的Responder就是对BeeMessage感兴趣的UI或者Model。看下图:

        iOS快速开发框架Bee-Framework应用和解析(三) - Message, Model, Signal0
        
        可以看到,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事件,主要有以下的特点:
         对象化的事件,可指定source, target         可携带附件对象         事件对象有通过带名字空间的三段取名方式。比如:"signal.NewsModel.RELOADED", 表示来源于NewsModel类型的RELOADED事件。         事件对象和接收端解耦合,接收端采用“固定前缀 + 事件名”的方法生成selector, 比如-(void) handleUISignal_NewsModel_RELOADED: (BeeUISignal*) signal;         普通UI对象可以自己实现signalTarget方法,自己决定UISignal的转发路径,比如UIView的转发路径是对应的[view viewController];
        BeeUISignal通过BeeUISignalBus转发,具体的转发顺序比较复杂,有兴趣的同学可以调试代码梳理清楚。 但事件的发送目标只有四个选择: 尝试给Target class,尝试给Observer classes,尝试给UIView的superView,尝试给某个class的signalTarget(UIView的signalTarget是UIViewController) 。通过这四个选择,BeeUISignal 既解决了定向发送(代替delegate),解决了观察者发送(NSNotification),也支持了UIView的Responder发送(UI Responder Chain),一种事件糅合了苹果常用的事件发送支持。

        可以看出,BeeUISignal比NSNotification的适用面更广,人为融合了多种通信模式。书写起来因为有宏也比较简单,具体写法可以参考开发者手册。可以看出BeeUISignal带来的好处还挺多,引入了一个齐全而稍显复杂的机制。如果不是针对UI的事件传送,或者简单的带附件的事件通知,个人认为不必引入BeeUISignal, 用NSNotification和delegate解决相关问题。

iOS快速开发框架Bee-Framework应用和解析(三) --- Message, Model, Signal

这一次分享一下BeeMessage, BeeModel, 和BeeUISignal。这三个东东就是Controller, Model, 和Event的主要实现。您也可以到Bee的/documents/...
  • u011173875
  • u011173875
  • 2015年02月14日 17:23
  • 2178

gstreamer学习笔记(3):message,event,signal区别

注:本篇笔记以gstreamer 1.8.1 版本为蓝本,若有出入的地方,请确认版本信息 message在gstreamer中,message或者说Bus message(因为message都是在GS...
  • xuanwolanxue
  • xuanwolanxue
  • 2017年03月27日 10:16
  • 884

iOS快速开发框架Bee-Framework应用和解析(二) --- Bee framework架构概览

在第二部分里,分享一下Bee Framework架构的看法。如果您下载了Bee Framework, 在/document/developer_manual.pdf有Bee的开发手册。手册里有典型的...
  • u011173875
  • u011173875
  • 2015年02月10日 18:39
  • 2343

iOS快速开发框架Bee-Framework应用和解析(一) --- 为什么使用Bee framework

去年夏天,兼职参与了一个创业项目iOS部分的开发。可能是iOS刚入门的原因吧,对苹果原生的开发方式有以下的不好的感觉:         1 巨型ViewController, 由于delegate和d...
  • u011173875
  • u011173875
  • 2015年02月09日 16:25
  • 3575

iOS快速开发框架Bee-Framework应用和解析(二) - Bee framework架构概览

原文: http://www.itnose.net/detail/6209552.html 2015-02-10 18:39   在第二部分里,分享一下Bee Framework架构的看法。如果您...
  • jiftlixu
  • jiftlixu
  • 2016年06月01日 01:32
  • 1466

iOS快速开发框架Bee-Framework应用和解析 (四,完结)UI容器,UICell, UILayout(XML + CSS)

作为Bee系列解析的最后一个部分,本文分享一下Bee的UI开发。Bee的UI开发很有特点:         BeeUI的核心是XML布局和风格。支持CSS语法,支持额外的布局优化,支持更统一...
  • u011173875
  • u011173875
  • 2015年02月14日 17:30
  • 2611

iOS 数据解析 JSONModel的介绍

·     IOS设备时常需要和服务器----一般来说是远程服务器进行数据交换。轻量级的APP应用只需少量的数据交互,例如每小时获取一次是否有更新的消息。另一些APP应用则需要与后台服务器有类似分享...
  • qq_33778243
  • qq_33778243
  • 2016年01月19日 20:33
  • 1417

【ios开发】教你如何建一个小的model,来接受后台传过来的字典或者数组

大多来说我们喜欢用一些,jsonkit和jsonmodel的第三方的库来解析,有没有简单的办法实现一个model呢,答案当然是有的。KVC模式 1、实现简单的model // // Pe...
  • wm9028
  • wm9028
  • 2016年04月13日 11:23
  • 3243

iOS开发setValuesForKeysWithDictionary生成model解析神器

在开发中,我们得到后台返回的json数据时,经常根据返回的字典数组格式然后创建一个model去解析数据,实质其实就是根据后台的字段进行一一对应,通过setValue forKey方法将一个字典进行包装...
  • MinggeQingchun
  • MinggeQingchun
  • 2017年03月29日 17:13
  • 725

ios如何将model转换成NSDictionary

- (NSDictionary *)properties_aps { NSMutableDictionary *props = [NSMutableDictionary dictionary...
  • u011452278
  • u011452278
  • 2015年10月27日 10:47
  • 1136
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS快速开发框架Bee-Framework应用和解析(三) - Message, Model, Signal
举报原因:
原因补充:

(最多只允许输入30个字)