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/...

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

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

    我是如何成为一名python大咖的?

    人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

    用.Net打造一个移动客户端(Android/IOS)的服务端框架NHM(三)——搭建Android开发环境,用Hibernate生成Android项目的Model层

    客户端开发环境 开发Android客户端,首先要做的是配置Android开发环境,相对于服务器端开发环境的配置,Android的开发环境要稍微复杂一些。这里,我们采用Eclipse+ADT+Hibe...

    快速浏览ios框架系列(一)----UIKit Framework

    除了外行,几乎人人都知道UIKit Framework的重要性。 在6.0时代UIKit Framework的头文件增加到了100多个,新人点开往往会吓一跳,不明觉厉,萌生退意。固,本文试图通过阐明每...

    开源框架iOS-Universal-Framework帮助快速建立一个共享的库

    开源框架,帮助快速建立一个共享的库,方便team开发: https://github.com/kstenerud/iOS-Universal-Framework 参考: http://blo...
    • gnicky
    • gnicky
    • 2012-05-06 22:42
    • 1202

    iOS-通过Message框架开发一个Sticker Pack(无需代码)(第一篇)

    一、概述 iOS 10 引入了Message框架,开发者可以为苹果内置的Messages应用开发扩展。 目的:通过开发一个应用扩展,可以让用户个能应用在Message应用中交互。 Message框架支...

    Flex快速入门系列之三:Parsley框架简单使用(IOC以及message机制)

    Parsley是一个开源的IOC容器也是一个完全解耦的基于消息中心机制的消息框架,它还为我们提供了一些很有用的工具类。Favous平台即将使用parsley的架构,来配置所有的bean,业务系统以后也...

    基于 SailingEase WinForm Framework 开发优秀的客户端应用程序(2:开始搭建模块化的程序框架)

    本系统文章将详细阐述客户端应用程序的设计理念,实现方法。 本系列文章以 SailingEase WinForm Framework 为基础进行设计并实现,但其中的设计理念及方法,亦适用于任何类型的...

    安卓应用程序插件化开发框架 -AAP Framework

    介绍 这个框架的初衷,是为了方便让程序模块化、插件化,将一个apk应用拆分为多个apk。 不明白这个插件化、模块化是怎么回事的话,可以看看腾讯微信的安卓客户端中的插件配置。  在这里我会以腾讯微...
    返回顶部
    收藏助手
    不良信息举报
    您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
    举报原因:
    原因补充:

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