zoukankan      html  css  js  c++  java
  • ReactiveCocoa基础知识内容2

    引用网络上一些实例的代码,针对ReactiveCocoa的运用可以更加有帮助;

    1:跟AF结合时的写法,返回RACSignal

    - (RACSignal *)fetchQuestionWithTag:(NSString *)tag {
        
        NSString *relativeURL = [NSString stringWithFormat:@"http://api.stackexchange.com/2.1/questions/?site=stackoverflow&order=desc&sort=hot&tagged=%@", tag];
        RACSignal *signal =
            [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
              
              AFHTTPRequestOperation *operation = [
                  [AFHTTPRequestOperationManager manager]
                  GET:relativeURL
                  parameters:nil
                  success:^(AFHTTPRequestOperation *operation, NSDictionary *responseObject) {
                      
                      [subscriber sendNext:responseObject[@"items"]];
                      [subscriber sendCompleted];
                  }
                  failure:^(AFHTTPRequestOperation *operation, NSError *error){
                      [subscriber sendError:error];
                  }];
                
                return [RACDisposable disposableWithBlock:^{
                    [operation cancel];
                }];
            }];
    
        return signal;
        
    }

     2:RACCommand的运用,作为事件响应

    定义一个ViewModel
    
    @interface SubscribeViewModel : NSObject
    
    @property(nonatomic, strong) RACCommand *subscribeCommand;
    
    // write to this property
    @property(nonatomic, strong) NSString *email;
    
    // read from this property
    @property(nonatomic, strong) NSString *statusMessage;
    
    @end
    @property(nonatomic, strong) RACSignal *emailValidSignal;
    
    实现代码:
    
    - (RACCommand *)subscribeCommand {
        if (!_subscribeCommand) {
            @weakify(self);
            _subscribeCommand = [[RACCommand alloc] initWithEnabled:self.emailValidSignal signalBlock:^RACSignal *(id input) {
                @strongify(self);
                return [SubscribeViewModel postEmail:self.email];
            }];
        }
        return _subscribeCommand;
    }
    
    + (RACSignal *)postEmail:(NSString *)email {
        AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
        manager.requestSerializer = [AFJSONRequestSerializer new];
        NSDictionary *body = @{@"email": email ?: @""};
        return [[[manager rac_POST:kSubscribeURL parameters:body] logError] replayLazily];
    }
    
    - (RACSignal *)emailValidSignal {
        if (!_emailValidSignal) {
            _emailValidSignal = [RACObserve(self, email) map:^id(NSString *email) {
                return @([email isValidEmail]);
            }];
        }
        return _emailValidSignal;
    }
    调用绑定:
    
    - (void)bindWithViewModel {
        RAC(self.viewModel, email) = self.emailTextField.rac_textSignal;
        self.subscribeButton.rac_command = self.viewModel.subscribeCommand;
        RAC(self.statusLabel, text) = RACObserve(self.viewModel, statusMessage);
    }
    
    - (UITextField *)emailTextField {
        if (!_emailTextField) {
            _emailTextField = [UITextField new];
            _emailTextField.borderStyle = UITextBorderStyleRoundedRect;
            _emailTextField.font = [UIFont boldSystemFontOfSize:16];
            _emailTextField.placeholder = NSLocalizedString(@"Email address", nil);
            _emailTextField.keyboardType = UIKeyboardTypeEmailAddress;
            _emailTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
        }
        return _emailTextField;
    }
    
    - (UIButton *)subscribeButton {
        if (!_subscribeButton) {
            _subscribeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            [_subscribeButton setTitle:NSLocalizedString(@"Subscribe", nil) forState:UIControlStateNormal];
        }
        return _subscribeButton;
    }
    
    - (UILabel *)statusLabel {
        if (!_statusLabel) {
            _statusLabel = [UILabel new];
        }
        return _statusLabel;
    }

    说明:RACCommand类用于表示事件的执行,一般来说是在UI上的某些动作来触发这些事件,比如点击一个按钮。RACCommand的实例能够决定是否可以被执行,这个特性能反应在UI上,而且它能确保在其不可用时不会被执行。通常,当一个命令可以执行时,会将它的属性allowsConcurrentExecution设置为它的默认值:NO,从而确保在这个命令已经正在执行的时候,不会同时再执行新的操作。命令执行的返回值是一个RACSignal,因此我们能对该返回值进行next:,completed或error:, 

    3:关于RACObserve的用法

    监听对象的成员变量变化,当成员变量值被改变时,触发做一些事情。 这种情况其实就是IOS KVO机制使用的场景,使用KVO实现,通常有三个步骤:1,给对象的成员变量添加监听;2,实现监听回调;3,取消监听;而通过RAC可以直接实现,RAC的回调是通过block实现的,类似于过程式编程,上下文也更容易理解一些。

    a: 场景:当前类有一个成员变量 NSString *input,当它的值被改变时,发送一个请求。

    [RACObserve(self, input)  
        subscribeNext:^(NSString* x){  
            request(x);//发送一个请求  
       }]; 

    说明:每次input值被修改时,就会调用此block,并且把修改后的值做为参数传进来。

    b:场景:在上面场景中,当用户输入的值以2开头时,才发请求.

    [[RACObserve(self, input)  
         filter:^(NSString* value){  
             if ([value hasPrefix:@"2"]) {  
                 return YES;  
             } else {  
                 return NO;  
             }  
         }]  
         subscribeNext:^(NSString* x){  
            request(x);//发送一个请求  
        }]; 

    c:上面场景是监听自己的成员变量,如果想监听UITextField输入值变化,框架也做了封装可以代替系统回调

    [[self.priceInput.rac_textSignal  
         filter:^(NSString *str) {  
             if (str.integerValue > 20) {  
                 return YES;  
             } else {  
                 return NO;  
             }  
         }]  
         subscribeNext:^(NSString *str) {  
        request(x);//发送一个请求 
    }];

    d:场景:button监听 两个输入框有值和一个成员变量值,当输入框有输入且成员变量为真时,button为可点击状态

    RAC(self.payButton,enabled) = [RACSignal  
                                       combineLatest:@[self.priceInput.rac_textSignal,  
                                                    self.nameInput.rac_textSignal,  
                                                    RACObserve(self, isConnected)  
                                                    ]  
                                       reduce:^(NSString *price, NSString *name, NSNumber *connect){  
                                       return @(price.length > 0 && name.length > 0 && [connect boolValue]);  
                                       }];  

    说明:同时监听多个变量变化,当这些变量满足一定条件时,使button为可点击状态

    e:场景:满足上面条件时,直接发送请求

    [[RACSignal  
                                       combineLatest:@[self.priceInput.rac_textSignal,  
                                                    self.nameInput.rac_textSignal,  
                                                    RACObserve(self, isConnected)  
                                                    ]  
                                       reduce:^(NSString *price, NSString *name, NSNumber *connect){  
                                       return @(price.length > 0 && name.length > 0 && ![connect boolValue]);  
                                       }]  
                                 subscribeNext:^(NSNumber *res){  
                                     if ([res boolValue]) {  
                                         NSLog(@"XXXXX send request");  
                                     }  
                                 }];  

    f:distinctUntilChanged直到收到不同值才响应,可以过滤掉那些不必要的网络请求等

        @weakify(self);
        
        //Start Binding our properties
        RAC(self.nameField,text) = [RACObserve(self.viewModel, playerName) distinctUntilChanged];
        
        [[self.nameField.rac_textSignal distinctUntilChanged] subscribeNext:^(NSString *x) {
            //this creates a reference to self that when used with @weakify(self);
            //makes sure self isn't retained
            @strongify(self);
            self.viewModel.playerName = x;
        }];

     4:RACScheduler为RAC调度类(主线程,子线程等)

    显示网络下载的图片

     RAC(self.imageView, image) = [[RACSignal startEagerlyWithScheduler:[RACScheduler schedulerWithPriority:RACSchedulerPriorityBackground]
     block:^(id <RACSubscriber> subscriber) {
     NSError *error;
     NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://ww3.sinaimg.cn/bmiddle/7128be06jw1ei4hfthoj3j20hs0bomyd.jpg"]
    options:NSDataReadingMappedAlways
    error:&error];
     if(error) {
     [subscriber sendError:error];
    }
     else {
     [subscriber sendNext:[UIImage imageWithData:data]];
     [subscriber sendCompleted];
    }
     }] deliverOn:[RACScheduler mainThreadScheduler]];

    说明:这段代码会在后台线程立即发起一个请求,然后传递到主线程上更新UI,主线程上执行[RACScheduler mainThreadScheduler],信号传递:- (RACSignal *)deliverOn:(RACScheduler *)scheduler

    5:控件结合的实例

    a:对uibutton添加了一个rac_signalForControlEvents的方式,就不用利用addtarget的方式来再写一个方法来进行对uibutton添加点击事件了。

    [[self.testBtn rac_signalForControlEvents:UIControlEventTouchUpInside]
     subscribeNext:^(id x) {
     TestViewController *testVC = [[TestViewController alloc] init];
     [self.navigationController pushViewController:testVC animated:YES];
    }];

    b:在UIAlertView的使用

    UIAlertView *chooseAlert = [[UIAlertView alloc] initWithTitle:@"选择图片上传"message:nil delegate:nil cancelButtonTitle:@"取消"otherButtonTitles:@"拍照上传", @"从相册选择", nil];
    [chooseAlert show];
    
    [[chooseAlert rac_buttonClickedSignal] subscribeNext:^(NSNumber *indexNumber) {
     if ([indexNumber intValue] == 1) {
     [self chooseFromCamera];
     } else if ([indexNumber intValue] == 2) {
     [self chooseFromAlbum];
    }
    }];

    c:在UITextfield的使用,self是因为我继承了一个textfield先进行功能添加和封装。所以self就是代指一个textfield了。

    [[self rac_signalForControlEvents:UIControlEventEditingDidBegin] 
     subscribeNext:^(NSNumber *editing) {
     self.bottomBorder.backgroundColor = [UIColor blackColor].CGColor;
    }];
    [[self rac_signalForControlEvents:UIControlEventEditingDidEnd] 
     subscribeNext:^(NSNumber *editing) {
     self.bottomBorder.backgroundColor = [UIColor grayColor].CGColor;
    }];

    说明:当选择这个框的时候,线会加粗变黑

    d:监控UIPagecontrol改变

    [RACObserve(self.imagePlayer.pageControl, currentPage) subscribeNext:^(id x) {
     [self refreshSlideContent:self.imagePlayer.pageControl.currentPage];
    }];

    不错的实例代码:

    ReactiveCocoa实用案例:http://www.saitjr.com/ios/ios-reactivecocoa-utility-demo.html

  • 相关阅读:
    mongodb添加登录验证--副本集环境
    kibana添加认证及权限--elasticsearch集群版
    Rabbitmq之exchange
    Elasticsearch集群下安装IK中文分词器
    cerebro安装--Elastic Stack之三
    elasticsearch-head安装方法--Elastic Stack之二
    动画小记——点击头像逐渐放大
    埋点
    picasso Failed to decode stream.
    记Sniper
  • 原文地址:https://www.cnblogs.com/wujy/p/4973177.html
Copyright © 2011-2022 走看看