ReactiveCocoa 代码阅读笔记 (2) Signal的实现机制
上篇讲了RAC和RACObserve两个宏的实现机制,但都是把RACSignal当作一个黑盒来理解。 本篇详细讲解Signal的内部机制。
创建Signal
Signal有很多种创建方式,例如
是用1
[UITextView rac_textSignal]
的方式。这里我们先看看
自定义创建的Signal:1
signalForSelector:
方法接收一个block, 把这个block存在1
createSignal
属性中。顾名思义,这个block会在1
_didSubscribe
的时候被调用。1
subscribe
subscribe一个signal
下面看最常用的
的定义1
subscribeNext
会创建一个1
subscribeNext
对象, 它保存了1
RACSubscriber
, 1
nextBlock
和1
errorBlock
,这些block将在1
completedBlock
, 1
sendNext
和1
sendError
时调用:1
sendCompleted
可以看到,
是线程安全的,并且1
sendNext
是和1
nextBlock
在同一个线程上执行的。1
sendNext
我们回到
, 1
RACSignal
会调用1
subscribeNext
:1
subscribe
可以看作和1
RACPassthroughSubscriber
功能一样,这里不细讲,所以1
subscriber
就是调用了1
subscribe:
并传入一个block, 在这个block中调用了1
RACScheduler.subscriptionScheduler schedule:
,也就是1
didSubscribe
中的block。所以我们可以得到一个结论:对于1
createSignal
创建的信号,每1
createSignal
一次,其block就被调用一次。1
subscribe
返回一个单例的1
RACScheduler.subscriptionScheduler
对象, 其1
RACSubscriptionScheduler
方法:1
schedule
这个方法会找
, 这个方法在主线程上或者在1
RACScheduler.currentScheduler
内部(schedule中的schedule)会返回非1
schedule
, 此时直接调用block; 如果不在主线程上,最外层schedule会使用1
nil
,也就是在一个background queue上执行block.1
backgroundScheduler
因此, 如果createSignal在主线程上执行,(之后调用subscribe时)signal的
(也就是1
didSubscribe
传入的block)也会在主线程上执行。1
createSignal
一般自定义的signal会在
这个block中(或者其后续)调用1
didSubscribe
等方法,这样1
[subscriber sendNext]
中传入的block就会执行。应该注意到的是1
subscribeNext:
中传入的block会和1
subscirbeNext:
在同一个线程上执行。1
sendNext
rac_signalForSelector:
这个方法很重要,它为各种1
rac_signalForSelector:
的delegate方法封装提供了基础。这个方法产生一个signal, 这个signal会在receiver执行某个selector时发送函数调用的参数。以UITextView为例:1
UIView
这里会用一个
作为1
self.rac_delegateProxy
的proxy,调用1
TextView
也就是产生了一个信号, 当1
[self.rac_delegateProxy signalForSelector:@selector(textViewDidChange:)]
调用时触发。1
[delegate textViewDidChange:]
中创建了一个1
rac_signalForSelector
(一个可以手动控制进行1
subject
的信号), 做了很复杂的swizzling, 其中和发送信号相关的是1
sendNext
, 这个方法改写了原本的1
RACSwizzleForwardInvocation
. 然后将自己的对应selector的方法替换成1
forwardInvocation
,这个1
forwardInvocation
里面会调用1
forwardInvocation
发送信号给subscriber.1
[subject sendNext:]
一句话概括:
会”劫持” 1
rac_textSignal
方法,然后在这个方法调用时,把这个方法传入的参数发送给subscriber。这个劫持过程的实现是由1
UITextView.delegate的textViewDidChange:
方法完成的。1
[NSObject rac_signalForSelector:]