美文网首页
ReactiveCocoa初探

ReactiveCocoa初探

作者: 少少白 | 来源:发表于2016-07-05 10:25 被阅读40次

    前一段项目中用到了ReactiveCocoa.今天做一下简单的总结,当然项目还在不断尝试ReactiveCocoa的最佳实践,希望自己还会有后续的文章 :)

    <h4>MVC</h4>
    一切要从我们熟悉的MVC架构开始,这个被戏称为Massive View Controller(臃肿的视图控制器)的软件架构如下:


    MVC架构
    • Model:Encapsulate the data specific to an application and define the logic and computation that manipulate and process that data.
    • View:Is an object in an application that users can see.
    • Controller: Acts as an intermediary between one or more of an application’s view objects and one or more of its model objects.
      From:Cocoa Core Competencies

    简单来说Model用于程序的基本数据对象,View用于UI控件展示,Controller用于粘合View和Model,将Model里的数据内容展示到UI上.
    CS193p上有幅图来表示MVC之间的关系及如何来进行通讯:

    MVC
    • Model层无法与View层进行通信的.
    • Controller能直接读写调用Model,Model通过Notification&KVO来和Controller进行通信
    • Controller可以直接和View层通信,通过outlet控制View上的控件,View可以通过action来射向Controller里的target来告诉Controller View中某个控件被点击等的操作.Controller还可以通过Protocol(delegate,datasource等)来对View进行控制.

    MVC在iOS开发中被广泛应用,然而慢慢你会发现他有些弊端,那就是大量的处理逻辑都塞进了ViewController里面,会使其代码行数变得不可控,于是就有人引入了MVVM.

    <h5>MVVM</h5>
    引用ReactiveCocoa and MVVM,an Introduction中的一幅图来说明MVVM与MVC之间的联系:

    MVVM & MVC

    简单来说ViewModel是将Controller里面的逻辑代码分离出来,使Controller只用于将处理好的数据与View对应起来.这就会产生一个问题:ViewModel如何与Controller进行通信呢?想到的最简单的就是delegate.然而笨重写法会使代码变得难看,而拯救我们的super man就是ReactiveCocoa.

    <h6>ReactiveCocoa的简单使用</h6>

    • 对值的监听
        [self.usernameTextField.rac_textSignal subscribeNext:^(id x) {
            NSLog(@"username = %@", x);
        }];
    
    • 对值的过滤
        [[self.usernameTextField.rac_textSignal
          filter:^BOOL(NSString *text) {
              return text.length > 5;
        }]
         subscribeNext:^(id x) {
             NSLog(@"filter x = %@", x);
        }];
    
    • 对值的处理转换
        [[[self.usernameTextField.rac_textSignal map:^id(NSString *text) {
            return @(text.length);
        }]
         filter:^BOOL(NSNumber *length) {
             return [length integerValue] > 5;
         }]
         subscribeNext:^(id x) {
             NSLog(@"username x = %@", x);
         }];
     
     RACSignal *validUsernameSignal = [self.usernameTextField.rac_textSignal
                                          map:^id(NSString *text) {
                                              return @([self isValidUsername:text]);
                                          }];
      - (BOOL)isValidUsername:(NSString *)username {
             return username.length > 5;
        }
    
    • 对值的监听
        RAC(self.passwordTextfield, backgroundColor) = [validPasswordSignal map:^id(NSNumber *passwordValid) {
            return [passwordValid boolValue] ? [UIColor clearColor] : [UIColor yellowColor];
        }];
    
    • 信号的融合
        RACSignal *validUsernameSignal = [self.usernameTextField.rac_textSignal
                                          map:^id(NSString *text) {
                                              return @([self isValidUsername:text]);
                                          }];
        
        RACSignal *validPasswordSignal = [self.passwordTextfield.rac_textSignal
                                          map:^id(NSString *text) {
                                              return @([self isValidPassword:text]);
                                          }];
        RACSignal *signUpActiveSignal = [RACSignal combineLatest:@[validUsernameSignal,  validPasswordSignal]
                                                          reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid){
                                                              return @([usernameValid boolValue] && [passwordValid boolValue]);
                                                          }];
        
        [signUpActiveSignal subscribeNext:^(NSNumber *signupActive) {
            self.loginButton.enabled = [signupActive boolValue];
        }];
    
    • 对事件的监听
        [[[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside]
         map:^id(id value) {
             return [self loginSignal];
         }]
         subscribeNext:^(id x) {
             NSLog(@"login result: %@", x);
         }];
    - (RACSignal *)loginSignal {
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            [self.loginService loginWithUsername:self.usernameTextField.text password:self.passwordTextfield.text complete:^(BOOL success) {
                [subscriber sendNext:@(success)];
                [subscriber sendCompleted];
            }];
            return nil;
        }];
    }
    

    Demo地址
    <h3>参考</h3>

    相关文章

      网友评论

          本文标题:ReactiveCocoa初探

          本文链接:https://www.haomeiwen.com/subject/aivtjttx.html