当前位置: 代码迷 >> Iphone >> ReactiveCocoa基础知识内容二
  详细解决方案

ReactiveCocoa基础知识内容二

热度:246   发布时间:2016-04-25 05:28:51.0
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:NSDataReadingMappedAlwayserror:&error]; if(error) { [subscriber sendError:error];} else { [subscriber sendNext:[UIImage imageWithData:data]]; [subscriber sendCompleted];} }] deliverOn:[RACScheduler mainThreadScheduler]];

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

  相关解决方案