ReactiveCocoa是一个将函数响应式编程范例带入Objective-C的开源库.
记录一下学习的过程。
环境搭建
通过CocoaPods导入ReactiveCocoa 编辑pod文件
use_frameworks! pod "ReactiveCocoa", "~> 4.1.0"
导入成功后即可使用
基本使用:
- 监听按钮事件
[[btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { NSLog(@"点击按钮"); }];
- 监听方法调用
[[self rac_signalForSelector:@selector(touchBtn:)] subscribeNext:^(id x) { NSLog(@"监听selector"); }];
- 文本信号
[_tf.rac_textSignal subscribeNext:^(id x) { _lbl.text = x; }];
- 宏定义使用
RAC(_lbl, text) = _tv.rac_textSignal; //KVO [RACObserve(_lbl, text) subscribeNext:^(id x) { NSLog(@"%@", x); }]; //元组 RACTuple *tuple = RACTuplePack(@3, @4); RACTupleUnpack(NSString *key, NSString *value) = tuple; NSLog(@"%@ %@", key, value);
- 网络请求
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.wukongcoo1.com/content/images/2016/04/----3.gif"]]; RACSignal *requestSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { [subscriber sendNext:data]; [subscriber sendCompleted]; }]; [task resume]; return nil; }]; [requestSignal subscribeNext:^(id x) { NSLog(@"请求到了 %@", x); }];
接下来介绍冷信号、热信号
冷信号
冷信号总结起来就是:信号源会对每一个订阅者发送完整的消息。
RACSignal *coldSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@1]; [subscriber sendNext:@2]; [subscriber sendNext:@3]; return nil; }]; [[RACScheduler mainThreadScheduler] afterDelay:0.1 schedule:^{ [coldSignal subscribeNext:^(id x) { NSLog(@"subscribor 1 receive %@", x); }]; }]; [[RACScheduler mainThreadScheduler] afterDelay:1 schedule:^{ [coldSignal subscribeNext:^(id x) { NSLog(@"subscribor 2 receive %@", x); }]; }];
热信号
而热信号呢,信号源只会对订阅者发送订阅之后的消息
RACMulticastConnection *connection = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [[RACScheduler mainThreadScheduler] afterDelay:1 schedule:^{ [subscriber sendNext:@1]; }]; [[RACScheduler mainThreadScheduler] afterDelay:2 schedule:^{ [subscriber sendNext:@2]; }]; [[RACScheduler mainThreadScheduler] afterDelay:3 schedule:^{ [subscriber sendNext:@3]; }]; [[RACScheduler mainThreadScheduler] afterDelay:4 schedule:^{ [subscriber sendCompleted]; }]; return nil; }] publish]; [connection connect]; RACSignal *signal = connection.signal; NSLog(@"Signal was created."); [[RACScheduler mainThreadScheduler] afterDelay:1.1 schedule:^{ [signal subscribeNext:^(id x) { NSLog(@"Subscriber 1 recveive: %@", x); }]; }]; [[RACScheduler mainThreadScheduler] afterDelay:2.1 schedule:^{ [signal subscribeNext:^(id x) { NSLog(@"Subscriber 2 recveive: %@", x); }]; }];
Map 与 FlattenMap
- Map
map的作用是对心法要发送的消息进行处理
RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@3]; return nil; }] map:^id(id value) { return [NSString stringWithFormat:@"map:%@", value]; }]; [signal subscribeNext:^(id x) { NSLog(@"%@", x); }];
- FlattenMap
FlattenMap的作用是对原有的信号进行订阅,从而生成新的信号,同时可以修改信号中的消息
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@3]; return nil; }] flattenMap:^RACStream *(id value) { return [RACReturnSignal return:[NSString stringWithFormat:@"输出:%@",value]]; }] subscribeNext:^(id x) { NSLog(@"%@", x); }];
实践
进行输入验证
RACSignal *canLoginSignal = [RACSignal combineLatest:@[ _usernameLabel.rac_textSignal, _pwdLabel.rac_textSignal] reduce:^(NSString *username, NSString *password){ NSLog(@"%@", username); return @(username.length > 5 && password.length > 5); }]; RAC(self.loginBtn, enabled) = canLoginSignal;
效果:
这里有demo的链接
参考资料
http://nshipster.cn/reactivecocoa/
http://tech.meituan.com/tag/ReactiveCocoa
http://www.jianshu.com/p/87ef6720a096