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