RAC之MVVM構架

我們這里首先用一個簡單的登錄頁面來說明一下MVVM構架,之后再用一個網絡請求深入一下MVVM

  • 1, 如果不使用MVVM構架,把所有的東西都寫在控制器中,比較臃腫,如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    //1,登錄按鈕可否點擊的業務邏輯
    RACSignal *combineSignal = [RACSignal combineLatest:@[_account.rac_textSignal, _pwd.rac_textSignal] reduce:^id(NSString *account, NSString *pwd){
        return @(account.length && pwd.length);
    }];
    /*
    [combineSignal subscribeNext:^(id x) {
        _login.enabled = [x boolValue];
    }];
     */
    RAC(_login,enabled) = combineSignal;
    
    
    //2,把點擊登錄按鈕邏輯抽離出來
    RACCommand  *loginCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        
        NSLog(@"在這里請求數據---%@----%@",_account.text ,_pwd.text);
       
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            [subscriber sendNext:@"把請求到的數據發送出去--在外面進行調用"];
            [subscriber sendCompleted];//這一步表示信息發送完成,之后調用會重新開始并發送信息,如果沒有這一句,下一次就不會發送消息出去
            return  nil;
        }];
    }];
    
    
    [loginCommand.executionSignals.switchToLatest subscribeNext:^(id x) {
        NSLog(@"在外部拿到的數據-------%@", x);
    }];
    
    
    //3, 監聽登錄按鈕點擊,執行命令的業務邏輯即可
    [[_login rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
       
        NSLog(@"點擊了登錄按鈕");
        //點擊的時候進行command的調用
        [loginCommand execute:nil];
    }];
}
  • 2,使用VMMV進行構架
  • 控制器中代碼只需要如下:
-(LoginViewModel *)loginVM{
    
    if(_loginVM == nil){
        _loginVM = [[LoginViewModel alloc] init];
    }
    return _loginVM;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // mvvm
    RAC(self.loginVM, account) = _account.rac_textSignal;
    RAC(self.loginVM, pwd) = _pwd.rac_textSignal;
    RAC(self.login, enabled) = _loginVM.loginEnableSignal;
    
    [[_login rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
        NSLog(@"點擊了登錄按鈕");
        [_loginVM.loginCommand execute:nil];
    }];
    
    [_loginVM.loginCommand.executionSignals.switchToLatest subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

}
  • 其余代碼都抽取到VM中了:
- (instancetype)init{
    
    if (self = [super init]) {
        
        //1,登錄按鈕屬性
        //RACObserve是觀察者宏, 一旦被觀察內容發生變化就發出信號
        _loginEnableSignal = [RACSignal combineLatest:@[RACObserve(self, account), RACObserve(self, pwd)] reduce:^id(NSString *account, NSString *pwd){
            return @(account.length && pwd.length);
        }];

        
        //2,登錄按鈕事件
        _loginCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
            
            NSLog(@"在這里請求數據---%@----%@",self.account, self.pwd);
            
            return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
                [subscriber sendNext:@"把請求到的數據發送出去--在外面進行調用"];
                [subscriber sendCompleted];//這一步表示信息發送完成,之后調用會重新開始并發送信息,如果沒有這一句,下一次就不會發送消息出去
                return  nil;
            }];
        }];
        
        
    }
    return self;
}
  • 3, 使用MVVM處理網絡登錄邏輯

  • 首先控制器中只需要如下代碼:

    //如果想要在外面拿到數據,需要先訂閱
    [self.requestVM.requestCommand.executionSignals.switchToLatest subscribeNext:^(id x) {
        NSLog(@"----%@",x);
    }];
    
    [self.requestVM.requestCommand execute:nil]; 

  • 其他邏輯代碼都放在VM中,需要注意的是,在存放邏輯代碼的時候,為了把請求到的數據傳遞出去,需要把請求代碼放在信號中,通過訂閱者發送出去,然后在命令中把信號返回就可以了。

- (RACCommand *)requestCommand{
   
   if (_requestCommand == nil) {
       
       _requestCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
           
           NSLog(@"請求網絡數據");
           
           
           RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
               
               AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
               
               [manager GET:@"https://api.douban.com/v2/book/search" parameters:@{@"q":@"美女"} progress:^(NSProgress * _Nonnull downloadProgress) {
               } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                   
                   NSLog(@"zhangdanfeng");
                   [subscriber sendNext:responseObject];
                   
               } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
               }];
               
               return  nil;
           }];
           
           return signal;
       }];
   }
   return _requestCommand;
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,813評論 25 708
  • 轉載:http://ios.jobbole.com/83602/ 最近工作比較忙,但還是出來更新博客了,今天給大家...
    VV木公子閱讀 4,105評論 3 28
  • 前言由于時間的問題,暫且只更新這么多了,后續還會持續更新本文《最快讓你上手ReactiveCocoa之進階篇》,目...
    Karos_凱閱讀 1,751評論 0 6
  • 六年的汗水、六年的辛勞、六年的點點滴滴都將銘刻在歷史的長河中,永遠不會抹去。因為那里有我與孩子們成長的足跡...
    唯美兒閱讀 639評論 6 8
  • SDImageCache 負責緩存圖片 可配置的參數:shouldDecompressImages 是否要解壓圖...
    cocoaroger閱讀 381評論 0 0