ReactiveObjC
ReactiveObjC是ReactiveCocoa的Objective-C版本,它是一个函数响应式编程框架。学习这个框架不仅仅是因为它功能强大好用,也因为我们可以从中学习函数响应式的编程思想。
学习项目地址:study for https://github.com/shuaiwang007/RAC
响应式编程
在响应式编程中输入方与接收方是一种绑定状态,输入改变会立刻改变接收方的值,不会因一次操作之后结束这种绑定。
ReactiveObjC接管了iOS中几乎所有类型的事件机制:addTarget、代理、通知、KVO、时钟、网络异步回调。
函数式编程
高阶函数:接受一个或多个函数作为输入,输出一个函数。在OC中就是用block作为入参,Swift中可用函数作为入参。
这种参数为函数的函数可以分为两类:escaping函数入参和noescape函数入参,区别在于这个入参的函数是在执行过程内被调用还是在执行过程外被调用。执行过程外(escaping)被调用的一般用于callback用途。
ReactiveObjC的组成
ReactiveObjC库的组成主要分为Core和UI两个大类。核心库定义的是RAC的一些类型和方法,UI部分是对Cocoa框架中的UI类进行RAC的扩展。
ReactiveObjC重点类
RACStream
继承关系:RACStream -> RACSignal -> RACSubject、RACStream -> RACSequence
RACSignal和RACSequence的父类,定义了流的基本操作。
两个类方法:+empty(返回空流)、+return:(返回包含return后的值的流)
concat:[signalA concat:signalB],第一个信号必须调用sendCompleted,串联两个信号,第一个信号执行完毕后(发送completed)执行第二个信号,订阅信号分别返回两个信号的返回值。
zipWith:[signalA zipWith:signalB],把两个信号压缩成一个信号,当两个信号都有返回值时压缩成一个包含元组RACTuple的信号返回,元组内值的顺序只与压缩顺序有关。
+zip:RACStream的类方法,压缩zip:之后传入的所有信号,新信号在当所有原信号都有返回值时返回。
+zip:reduce:压缩zip:之后传入的所有信号,新信号在当所有原信号都有返回值时返回到reduce中,reduce中可以重新处理返回值再返回。
RACSignal 一对一单向数据流(核心类)
- (RACSignal*)then:(RACSignal* (^)(void))block:方法接受方信号执行完后,执行block中返回的信号,整个组合信号只返回then之后block中的信号中的值。
combine:reduce:多个信号聚合成一个信号,原信号的每个返回值都会在新信号中返回,在reduce中可以对返回值做操作。
merge:[signalA merge:signalB],安装原来信号值的返回顺序,在新信号中直接返回。
RACSubject
RACSequence
RACMulticastConnection 一对多单向数据流
RACCommand
RACCommand也是一个信号,它返回的也是一个信号,这个返回信号上带有数据,主要用来封装一些请求和事件。
RACCommand必须返回信号,信号可以为空。
RACCommand必须强引用。
RACCommand发送完数据必须发送完成信号。
executionSignals:返回一个包含signals的信号,-execute:成功调用后在主线程返回signals。
switchToLatest:当signals中的信号发出next、error或者completed时,返回该信号。
executing:返回YES or NO,表示是否有信号在执行,监听此信号获得是否完成的状态。
enable:返回当前是否可执行,监听此信号获得是否可执行的状态。
errors:监听此信号,错误会在errors信号的next事件中返回。
allowsConcurrentExecution:是否允许并行执行,默认NO。
参考文章
RACChannel 一对一双向数据流
RACChannel两端都是RACSignal(RACChannelTerminal),他们可以彼此互相发送信号。
RACChannel包含两个属性leadingTerminal和followingTerminal。
leadingTerminal订阅者一般为Model;followingTerminal订阅者一般为View。
对Model的操作会通过leadingTerminal发送给followingTerminal,并通知followingTerminal的订阅者;反之对View的操作会通过followingTerminal发送给leadingTerminal,并通知leadingTerminal的订阅者。
RACKVOChannel中的宏定义RACChannelTo(对象,属性,默认值)可以快速实现双向绑定。
RACChannelTo(对象,属性,默认值)相当于一个get方法获取RACChannelTerminal。
RACChannelTo(model, property) = RACChannelTo(view, property)这是一种快速实现双向绑定的方法,实现过程是在宏定义中的set方法里实现的双向绑定。
viewModel和视图属性双向绑定不完整的时候解决办法:
RACChannelTo(self, viewModel.mobile) = self.mobileTf.textChannelTerminal; RACChannelTo(self, viewModel.password) = self.pwdTf.textChannelTerminal; [self.mobileTf.textSignal subscribeNext:^(id _Nullable x) { @strongify(self) self.viewModel.mobile = x; }];
参考文章
ReactiveObjC常用方法
rac_signalForSelector:监听方法调用。
RACObserver(内部实现rac_valuesAndChangesForKeyPath):监听某个对象的属性改变。
rac_signalForControlEvents:用于监听某个事件。
rac_addObserverForName:用于监听某个通知,需要与takeUntil结合使用。
rac_liftSelector:当传入的Signals(信号数组),每一个signal都至少sendNext过一次,就会去触发第一个selector参数的方法。
RACSignal interval:onScheduler:定时器
RACSchedular.mainSchedular after: schedule: 延迟启动
信号的一般组合方法有:concat、zipWith、merge、combine、then