你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS快速開發框架Bee-Framework應用和解析(三) --- Message, Model, Signal

iOS快速開發框架Bee-Framework應用和解析(三) --- Message, Model, Signal

編輯:IOS開發綜合

這一次分享一下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。看下圖:
\ 可以看到,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]);

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解決相關問題。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved