RAC 被描述为函数响应式编程
编程思想
函数式编程 :使用高阶函数,例如函数用其他函数作为参数。
响应式编程:关注于数据流和变化传播。
链式编程 : 是将多个操作(多行代码)通过点号(.)链接在一起成为一句代码,使代码可读性好。a(1).b(2).c(3),注意点:要想达到链式编程方法的返回值必须是一个( (返回值是本身对象的)block)
入门 Signal 传递的 data Signal 传递的 data 是 event,它所传递的 event 包括 3 种:值事件、完成事件和错误事件。在传递值事件时,可以携带数据.
传递值事件/完成事件/错误事件的本质就是向 sub scriber 发送sendNext:、sendComplete以及sendError:消息
Signal的简单使用 创建信号、订阅信号、订阅过程å
创建单元信号
创建动态信号
通过 Cocoa 桥接
从别的信号变换而来
由序列变换而来
Cocoa桥接
1 2 3 4 RACSignal *signal6 = [objectrac_signalForSelector:@selector (setFrame:)]; RACSignal *signal7 = [control rac_signalForControlEvents:UIControlEventTouchUpInside ]; RACSignal *signal8 = [object rac_willDeallocSignal]; RACSignal *signal9 = RACObserve(object, keyPath);
信号变换
1 2 3 RACSignal *signal10 = [signal1 map:^id (id value) { return someObject;}];
序列变换
1 RACSignal *signal11 = sequence.signal;
订阅信号的方式有 3 种:
通过subscribeNext:error:completed:方法订阅
RAC 宏绑定
Cocoa 桥接
通过subscribeNext:error:completed:方法订阅
1 2 3 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock error:(void (^)(NSError *error))errorBlock completed:(void (^)(void ));
RAC 宏绑定
1 RAC(view, backgroundColor) = signal10;
Cocoa 桥接
1 2 3 [object rac_liftSelector:@selector (someSelector:) withSignals:signal1, signal2, nil ]; [object rac_liftSelector:@selector (someSelector:) withSignalsFromArray:@[signal1, signal2]]; [object rac_liftSelector:@selector (someSelector:) withSignalOfArguments:signal1];
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) { [subscriber sendNext:@"1" ]; [subscriber sendNext:@"2" ]; [subscriber sendCompleted]; [subscriber sendNext:@"3" ]; return [RACDisposable disposableWithBlock:^{ NSLog (@"dispose" ); }]; }]; [signal subscribeNext:^(id x) { NSLog (@"next value is : %@" , x);} error:^(NSError *error) { NSLog (@"error : %@" , error);} completed:^{ NSLog (@"completed" );}];
RACSignal的每一个操作都会返回一个RACSignal。
RACSequence是RAC中的集合类,可以实现OC对象与信号中传递值之间的转换,RAC类库中提供了NSArray,NSDictionary等集合类的分类供其转换
可能遇到的坑 接收不到信号 1 2 3 4 5 6 7 8 9 [RACObserve(self , selectedRows) subscribeNext:^(NSSet *currentlySelected) { NSLog (@"Currently selected: %@" , currentlySelected);}]; self .selectedRows = [NSMutableSet set];- (void )tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self .selectedRows addObject:indexPath]; }
上面RACObserve回调只会调用一次,初始化的时候,为什么addObject的时候没有出发信号? 因为addObject没有触发KVO事件。解决通过协议触发KVO
1 2 3 4 - (void )tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [[self mutableSetValueForKey:@"selectedRows" ] addObject:indexPath]; }
需要关联多个信号 1 RAC(self .loginVM,pwdStr)=[RACSignal merge:@[passwordTxt.rac_textSignal,RACObserve(passwordTxt, text)]];
冷信号和热信号 冷热信号的概念源于.NET框架Reactive Extensions(RX)中的Hot Observable和Cold Observable,两者的区别是:
Hot Observable是主动的,尽管你并没有订阅事件,但是它会时刻推送,就像鼠标移动;而Cold Observable是被动的,只有当你订阅的时候,它才会发布消息。
Hot Observable可以有多个订阅者,是一对多,集合可以与订阅者共享信息;而Cold Observable只能一对一,当有不同的订阅者,消息是重新完整发送。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 -(void )racColdSingle { RACSignal* coldSingle=[RACSignal createSignal:^RACDisposable * _Nullable(id <RACSubscriber> _Nonnull subscriber) { [subscriber sendNext:@1 ]; [subscriber sendNext:@2 ]; [subscriber sendNext:@3 ]; [subscriber sendCompleted]; return nil ; }]; NSLog (@"Signal was created." );[[RACScheduler mainThreadScheduler] afterDelay:0.1 schedule:^{ [coldSingle subscribeNext:^(id x) { NSLog (@"Subscriber 1 recveive: %@" , x); }]; }]; [[RACScheduler mainThreadScheduler] afterDelay:1 schedule:^{ [coldSingle subscribeNext:^(id x) { NSLog (@"Subscriber 2 recveive: %@" , x); }]; }]; }
1 2 3 4 5 6 7 2019-09-23 14:14:26.853285+0800 RACDemo[16585:117906] Signal was created. 2019-09-23 14:14:26.956126+0800 RACDemo[16585:117906] Subscriber 1 recveive: 1 2019-09-23 14:14:26.956339+0800 RACDemo[16585:117906] Subscriber 1 recveive: 2 2019-09-23 14:14:26.956559+0800 RACDemo[16585:117906] Subscriber 1 recveive: 3 2019-09-23 14:14:27.888112+0800 RACDemo[16585:117906] Subscriber 2 recveive: 1 2019-09-23 14:14:27.888267+0800 RACDemo[16585:117906] Subscriber 2 recveive: 2 2019-09-23 14:14:27.888363+0800 RACDemo[16585:117906] Subscriber 2 recveive: 3
信号在14:14:26.853时被创建,14:14:26.956依次接到1、2、3三个值,而在14:14:27.888再依次接到1、2、3三个值。说明了变量名为coldSingle的这个信号,在两个不同时间段的订阅过程中,分别完整地发送了所有的消息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 -(void )racHoltSingal { 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); }]; }]; }
1 2 3 4 2019-09-23 14:20:26.214718+0800 RACDemo[16872:122429] Signal was created. 2019-09-23 14:20:28.325190+0800 RACDemo[16872:122429] Subscriber 1 recveive: 2 2019-09-23 14:20:29.274356+0800 RACDemo[16872:122429] Subscriber 1 recveive: 3 2019-09-23 14:20:29.274537+0800 RACDemo[16872:122429] Subscriber 2 recveive: 3
分析
创建了一个信号,在1秒、2秒、3秒分别发送1、2、3这三个值,4秒发送结束信号。
对这个信号调用publish方法得到一个RACMulticastConnection。
让connection进行连接操作。
获得connection的信号。
分别在1.1秒和2.1秒订阅获得的信号。
热信号是主动的,即使你没有订阅事件,它仍然会时刻推送。如第二个例子,信号在50秒被创建,51秒的时候1这个值就推送出来了,但是当时还没有订阅者。而冷信号是被动的,只有当你订阅的时候,它才会发送消息。如第一个例子。
热信号可以有多个订阅者,是一对多,信号可以与订阅者共享信息。如第二个例子,订阅者1和订阅者2是共享的,他们都能在同一时间接收到3这个值。而冷信号只能一对一,当有不同的订阅者,消息会从新完整发送。如第一个例子,我们可以观察到两个订阅者没有联系,都是基于各自的订阅时间开始接收消息的。
[RACSignal publish]、- [RACMulticastConnection connect]、- [RACMulticastConnection signal]这几个操作生成了一个热信号
在RAC中,所有的热信号都属于一个类RACSubject
冷信号与热信号的本质区别在于是否保持状态,冷信号的多次订阅是不保持状态的,而热信号的多次订阅可以保持状态,所以一种将冷信号转换为热信号的方法就是,将冷信号订阅,订阅到的每一个时间通过RACSubject发送出去,其它订阅者只订阅这个RACSubject
参考
(RAC)知其所以然(源码分析)
美团ReactiveCocoa