函数式编程思想: 把操作尽量写成一系例嵌套的函数或者方法调用。
函数式编程本质: 就是往方法中传入Block,方法中嵌套Block调用,把代码聚合起来管理
函数式编程特点: 每个方法必须有返回值(本身对象),把函数或者Block当做参数,block参数(需要操作的值)block返回值(操作结果)
代表:ReactiveCocoa。
链式编程思想:是将多个操作(多行代码)通过点号(.)链接在一起成为一句代码,使代码可读性好。a(1).b(2).c(3)
链式编程特点:方法的返回值是block,block必须有返回值(本身对象),block参数(需要操作的值)
代表:Masonry框架。
##ReactiveCocoa常见类
学习框架首要之处:个人认为先要搞清楚框架中常用的类,在RAC中最核心的类
RACSiganl
,搞定这个类就能用ReactiveCocoa开发了。
RACSiganl
:信号类,一般表示将来有数据传递,只要有数据改变,信号内部接收到数据,就会马上发出数据。
注意:
- 信号类(
RACSiganl
),只是表示当数据改变时,信号内部会发出数据,它本身不具备发送信号的能力,而是交给内部一个订阅者去发出。
- 默认一个信号都是冷信号,也就是值改变了,也不会触发,只有订阅了这个信号,这个信号才会变为热信号,值改变了才会触发。
- 如何订阅信号:调用信号
RACSignal
的subscribeNext
就能订阅
RACSubscriber
:表示订阅者的意思,用于发送信号,这是一个协议,不是一个类,只要遵守这个协议,并且实现方法才能成为订阅者。通过create创建的信号,都有一个订阅者,帮助他发送数据。`
objc
-(void)createSimpleSignal{
// RACSignal使用步骤:
// 1.创建信号 + (RACSignal )createSignal:(RACDisposable (^)(idsubscriber))didSubscribe
// 2.订阅信号,才会激活信号. - (RACDisposable * )subscribeNext:(void (^)(id x))nextBlock
// 3.发送信号 - (void)sendNext:(id)value
// RACSignal底层实现:
// 1.创建信号,首先把didSubscribe保存到信号中,还不会触发。
// 2.当信号被订阅,也就是调用signal的subscribeNext:nextBlock
// 2.2 subscribeNext内部会创建订阅者subscriber,并且把nextBlock保存到subscriber中。
// 2.1 subscribeNext内部会调用siganl的didSubscribe
// 3.siganl的didSubscribe中调用[subscriber sendNext:@1];
// 3.1 sendNext底层其实就是执行subscriber的nextBlock
// 1.创建信息
RACSignal signal = [RACSignal createSignal:^RACDisposable _Nullable(id
// block调用时刻:每当有订阅者订阅信号,就会调用block。
// 2.发送信号
[subscriber sendNext:@1];
// 如果不在发送数据,最好发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号。
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// block调用时刻:当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号。
// 执行完Block后,当前信号就不在被订阅了。
NSLog(@"信号销毁了");
}];
}];
// 3. 订阅信号,才会激活信号
[signal subscribeNext:^(id x) {
// block调用时刻:每当有信号发出数据,就会调用block.
NSLog(@”接收到数据:%@”,x);
}];
}
3. `RACDisposable`:用于取消订阅或者清理资源,当信号发送完成或者发送错误的时候,就会自动触发它。
**使用场景**: 不想监听某个信号时,可以通过它主动取消订阅信号。
4. `RACSubject`: 信号提供者,自己可以充当信号,又能发送信号。
**使用场景**: 通常用来代替代理,有了它,就不必要使用代理了
1. `RACReplaySubject`:重复提供信号类,`RACSubject`的子类。
> `RACReplaySubject`可以先发送信号,在订阅信号,`RACSubject`就不可以
**使用场景一**:如果一个信号每被订阅一次,就需要把之前的值重复发送一遍,使用重复提供信号类。
**使用场景二**:可以设置capacity数量来限制缓存的value的数量,即只缓充最新的几个值。
```objc
-(void)createRACSubject{
// RACSubject使用步骤
// 1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block。
// 2.订阅信号 - (RACDisposable * ) subscribeNext:(void (^)(id x))nextBlock
// 3.发送信号 sendNext:(id)value
// RACSubject:底层实现和RACSignal不一样。
// 1.调用subscribeNext订阅信号,只是把订阅者保存起来,并且订阅者的nextBlock已经赋值了。
// 2.调用sendNext发送信号,遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock
//1. 创建信号
RACSubject * subject = [RACSubject subject];
//2.订阅信号
[subject subscribeNext:^(id x) {
// block调用时刻:当信号发出新值,就会调用.
NSLog(@"第一个订阅都:%@",x);
}];
[subject subscribeNext:^(id x) {
// block调用时刻:当信号发出新值,就会调用.
NSLog(@"第二个订阅都:%@",x);
}];
//3. 发送信息
[subject sendNext:@"1"];
}
-(void)createReplaySubject{
// RACReplaySubject使用步骤:
// 1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block。
// 2.可以先订阅信号,也可以先发送信号。
// 2.1 订阅信号 - (RACDisposable * )subscribeNext:(void (^)(id x))nextBlock
// 2.2 发送信号 sendNext:(id)value
// RACReplaySubject:底层实现和RACSubject不一样。
// 1.调用sendNext发送信号,把值保存起来,然后遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。
// 2.调用subscribeNext订阅信号,遍历保存的所有值,一个一个调用订阅者的nextBlock
// 如果想当一个信号被订阅,就重复播放之前所有值,需要先发送信号,在订阅信号。
// 也就是先保存值,在订阅值。
// 1.创建信号
RACReplaySubject * replaySuject = [RACReplaySubject subject];
// 2. 发送信号
[replaySuject sendNext:@1];
[replaySuject sendNext:@2];
// 3.订阅信号
[replaySuject subscribeNext:^(id x) {
NSLog(@"第一个订阅者接收到的数据%@",x);
}];
[replaySuject subscribeNext:^(id x) {
NSLog(@" 第二个订阅者接收到的数据%@",x);
}];
}
RACTuple
:元组类,类似NSArray
,用来包装值.RACSequence
:RAC中的集合类,用于代替NSArray
,NSDictionary
,可以使用它来快速遍历数组和字典。`
objc
-( void )RACIterator{
// 1.遍历数组
NSArray * numbers = @[@1,@3,@4];
// 这里其实是三步
// 第一步: 把数组转换成集合RACSequence numbers.rac_sequence
// 第二步: 把集合RACSequence转换RACSignal信号类,numbers.rac_sequence.signal
// 第三步: 订阅信号,激活信号,会自动把集合中的所有值,遍历出来。
[numbers.rac_sequence.signal subscribeNext:^(id x) {NSLog(@"%@",x);
}];
// 2.遍历字典,遍历出来的键值对会包装成RACTuple(元组对象)
NSDictionary dict = @{@”name”:@”yuanph”,@”age”:@18,@”country”:@”china”};
[dict.rac_sequence.signal subscribeNext:^(RACTuple x) {// 解包元组,会把元组的值,按顺序给参数里面的变量赋值 RACTupleUnpack(NSString * key,NSString * value)= x; NSLog(@"%@:%@",key,value);
}];
}
`
RACCommand
:RAC
中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程
使用场景:监听按钮点击,网络请求