上一篇我们探索了RAC
的核心流程就是:
- 创建信号
- 订阅信号
- 订阅者发送信号
- 销毁
那么我们根据这些操作来看看RAC
的核心类以及具体实现,主要就是信号、订阅、销毁这3个点。
RACSignal
RACSiganl
,信号类,是抽象类RACStream
的子类。在RAC
中,万物皆信号,只有有了信号,才会有的一系列操作。一般表示将来有数据传递,只要有数据改变,信号内部接收到数据,就会马上发出数据。但是它本身不具备发送信号的能力,而是交给内部一个订阅者去发出。
+ (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
}
而最终的订阅方法的实现是由RACDynamicSignal
来完成的。该类有2个方法,一个就是创建信号,保存信号创建的回调;另一个就是执行订阅方法的时候调用信号创建保存的block
,返回销毁者。
+ (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
- (RACDisposable *)subscribe:(id)subscriber {
NSCParameterAssert(subscriber != nil);
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
if (self.didSubscribe != NULL) {
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
RACDisposable *innerDisposable = self.didSubscribe(subscriber);
[disposable addDisposable:innerDisposable];
}];
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
RACPassthroughSubscriber
核心订阅类RACPassthroughSubscriber
实现了一个协议RACSubscriber
,实现了该协议就有订阅信号,接收值处理值的能力。
- (instancetype)initWithSubscriber:(id)subscriber signal:(RACSignal *)signal disposable:(RACCompoundDisposable *)disposable {
NSCParameterAssert(subscriber != nil);
self = [super init];
_innerSubscriber = subscriber;
_signal = signal;
_disposable = disposable;
[self.innerSubscriber didSubscribeWithDisposable:self.disposable];
return self;
}
-
subscriber
:核心订阅者 -
signal
:信号 -
disposable
:销毁者
那我们再来看看, RACSubscriber
这个协议都定义了那些方法
- 保存
nextBlock
、错误信息、完成信息。
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
RACSubscriber *subscriber = [[self alloc] init];
subscriber->_next = [next copy];
subscriber->_error = [error copy];
subscriber->_completed = [completed copy];
return subscriber;
}
- 发送正常的信号,然后执行数据的回调。
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
- 发送错误,会销毁信号,然后回调错误,以后再也不接收这个信号的变化了。
- (void)sendError:(NSError *)e {
@synchronized (self) {
void (^errorBlock)(NSError *) = [self.error copy];
[self.disposable dispose];
if (errorBlock == nil) return;
errorBlock(e);
}
}
- 发送完成信号,会销毁信号,然后回调完成的操作,同样,以后再也不接收这个信号的变化了。
- (void)sendCompleted {
@synchronized (self) {
void (^completedBlock)(void) = [self.completed copy];
[self.disposable dispose];
if (completedBlock == nil) return;
completedBlock();
}
}
可以看到sendError
和sendCompleted
是在方法里就会销毁,那么sendNext
是什么时候销毁呢?就是调用者销毁的时候,也就是我们所说的self
或者viewController
销毁的时候。就会调用到RACSubscriber
重写的dealloc
方法。
- (void)dealloc {
[self.disposable dispose];
}
RACScheduler
Schedulers are used to control when and where work is performed.
调度者,用于控制工作何时何地执行。其实,它就是对GCD
的封装。
当我们在- (RACDisposable *)subscribe:(id
方法中调用schedule
方法的时候,会判断是否有currentScheduler
,如果有执行schedule
中的block
,没有的话就使用自己定义的backgroundScheduler
,进行处理block
。
- (RACDisposable *)schedule:(void (^)(void))block {
NSCParameterAssert(block != NULL);
if (RACScheduler.currentScheduler == nil) return [self.backgroundScheduler schedule:block];
block();
return nil;
}
会先从threadDictionary
里面获取RACScheduler
,如果获取的值不为nil
就将其值返回,用来调用信号的处理。如果为空的话,再来判断当前的任务是否在主队列或者主线程,如果是的话就返回自己封装的GCD
主队列用来调用。
+ (RACScheduler *)currentScheduler {
RACScheduler *scheduler = NSThread.currentThread.threadDictionary[RACSchedulerCurrentSchedulerKey];
if (scheduler != nil) return scheduler;
if ([self.class isOnMainThread]) return RACScheduler.mainThreadScheduler;
return nil;
}
+ (BOOL)isOnMainThread {
return [NSOperationQueue.currentQueue isEqual:NSOperationQueue.mainQueue] || [NSThread isMainThread];
}
+ (RACScheduler *)mainThreadScheduler {
static dispatch_once_t onceToken;
static RACScheduler *mainThreadScheduler;
dispatch_once(&onceToken, ^{
mainThreadScheduler = [[RACTargetQueueScheduler alloc] initWithName:@"org.reactivecocoa.ReactiveObjC.RACScheduler.mainThreadScheduler" targetQueue:dispatch_get_main_queue()];
});
return mainThreadScheduler;
}
_backgroundScheduler
其实也是一个默认优先级的全局串行队列,它是由RACTargetQueueScheduler
生成的实例。
RACTargetQueueScheduler, A scheduler that enqueues blocks on a private serial queue, targeting an arbitrary GCD queue.
而RACTargetQueueScheduler
是在任意的GCD
的线程中创建一个串行队列,然后将这些待处理的block
都放在这个串行对劣质,让调度者处理的block
能够同步执行,也就是让信号的任务同步执行。
_backgroundScheduler = [RACScheduler scheduler];
+ (RACScheduler *)scheduler {
return [self schedulerWithPriority:RACSchedulerPriorityDefault];
}
+ (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority {
return [self schedulerWithPriority:priority name:@"org.reactivecocoa.ReactiveObjC.RACScheduler.backgroundScheduler"];
}
// 创建一个全局的并发队列
+ (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority name:(NSString *)name {
return [[RACTargetQueueScheduler alloc] initWithName:name targetQueue:dispatch_get_global_queue(priority, 0)];
}
- (instancetype)initWithName:(NSString *)name targetQueue:(dispatch_queue_t)targetQueue {
NSCParameterAssert(targetQueue != NULL);
if (name == nil) {
name = [NSString stringWithFormat:@"org.reactivecocoa.ReactiveObjC.RACTargetQueueScheduler(%s)", dispatch_queue_get_label(targetQueue)];
}
// 此处使用串行队列的原因就是想要信号一个一个的处理
dispatch_queue_t queue = dispatch_queue_create(name.UTF8String, DISPATCH_QUEUE_SERIAL);
if (queue == NULL) return nil;
// 防止信号并发处理
dispatch_set_target_queue(queue, targetQueue);
return [super initWithName:name queue:queue];
}
全局串行队列调度处理的方式如下:
- (RACDisposable *)schedule:(void (^)(void))block {
NSCParameterAssert(block != NULL);
RACDisposable *disposable = [[RACDisposable alloc] init];
dispatch_async(self.queue, ^{
if (disposable.disposed) return;
[self performAsCurrentScheduler:block];
});
return disposable;
}
- (void)performAsCurrentScheduler:(void (^)(void))block {
NSCParameterAssert(block != NULL);
// 获取当前的调度者
RACScheduler *previousScheduler = RACScheduler.currentScheduler;
NSThread.currentThread.threadDictionary[RACSchedulerCurrentSchedulerKey] = self;
// 先执行调度的block
autoreleasepool {
block();
}
if (previousScheduler != nil) {
// 如果不是空的 放入threadDictionary
NSThread.currentThread.threadDictionary[RACSchedulerCurrentSchedulerKey] = previousScheduler;
} else {
// 如果是空的就移除threadDictionary中对应的值
// 执行下一次schedule操作的又会进入一次新的判断
[NSThread.currentThread.threadDictionary removeObjectForKey:RACSchedulerCurrentSchedulerKey];
}
}
验证一下:
- 主线程执行调度
- 子线程执行调度
可以看出当在主线程中使用信号的时候,调度者是把主线程的中的信号任务加入到主线程串行队列中执行,而在子线程中使用信号的时候,调度者会自己创建一个子线程,并把任务都加入到自己创建的这个子线程同步队列中执行。整个流程大致如下:
RACDisposable
& RACCompoundDisposable
RACDisposable
,销毁者,取消订阅,销毁订阅信号操作中间生成的一些辅助销毁对象。
RACCompoundDisposable
继承自RACDisposable
,它和RACDisposable
的区别是RACDisposable
是单个销毁者,RACCompoundDisposable
是销毁者集合,它管理着一个或者多个RACDisposable
。
- (instancetype)initWithBlock:(void (^)(void))block {
NSCParameterAssert(block != nil);
self = [super init];
// 保存销毁后续操作的block
_disposeBlock = (void *)CFBridgingRetain([block copy]);
OSMemoryBarrier();
return self;
}
+ (instancetype)disposableWithBlock:(void (^)(void))block {
return [[self alloc] initWithBlock:block];
}
- (void)dealloc {
if (_disposeBlock == NULL || _disposeBlock == (__bridge void *)self) return;
CFRelease(_disposeBlock);
_disposeBlock = NULL;
}
- (void)dispose {
void (^disposeBlock)(void) = NULL;
while (YES) {
void *blockPtr = _disposeBlock;
// 防止多线程操作引发的错误
if (OSAtomicCompareAndSwapPtrBarrier(blockPtr, NULL, &_disposeBlock)) {
if (blockPtr != (__bridge void *)self) {
disposeBlock = CFBridgingRelease(blockPtr);
}
break;
}
}
// 执行销毁后续的block
if (disposeBlock != nil) disposeBlock();
}
当订阅者调用dealloc
方法的时候执行[self.disposable dispose]
,由于销毁者都被RACCompoundDisposable
管理,就会调用[RACCompoundDisposable dispose]
,在这个方法中,遍历管理的销毁者,找到对应需要销毁的,然后调用[RACDisposable dispose]
进行销毁。
+ (instancetype)compoundDisposable {
return [[self alloc] initWithDisposables:nil];
}
+ (instancetype)compoundDisposableWithDisposables:(NSArray *)disposables {
return [[self alloc] initWithDisposables:disposables];
}
- (instancetype)init {
self = [super init];
const int result __attribute__((unused)) = pthread_mutex_init(&_mutex, NULL);
return self;
}
- (instancetype)initWithDisposables:(NSArray *)otherDisposables {
self = [self init];
// 将所有disposable保存到_inlineDisposables
#if RACCompoundDisposableInlineCount
[otherDisposables enumerateObjectsUsingBlock:^(RACDisposable *disposable, NSUInteger index, BOOL *stop) {
self->_inlineDisposables[index] = disposable;
if (index == RACCompoundDisposableInlineCount - 1) *stop = YES;
}];
#endif
// 相对应的添加操作
if (otherDisposables.count > RACCompoundDisposableInlineCount) {
_disposables = RACCreateDisposablesArray();
CFRange range = CFRangeMake(RACCompoundDisposableInlineCount, (CFIndex)otherDisposables.count - RACCompoundDisposableInlineCount);
CFArrayAppendArray(_disposables, (__bridge CFArrayRef)otherDisposables, range);
}
return self;
}
- (instancetype)initWithBlock:(void (^)(void))block {
RACDisposable *disposable = [RACDisposable disposableWithBlock:block];
return [self initWithDisposables:@[ disposable ]];
}
// 向RACCompoundDisposable管理集合中添加 RACDisposable
// 将disposable添加到_inlineDisposables
// 如果_inlineDisposables满了就添加到_disposables
- (void)addDisposable:(RACDisposable *)disposable {
NSCParameterAssert(disposable != self);
if (disposable == nil || disposable.disposed) return;
BOOL shouldDispose = NO;
pthread_mutex_lock(&_mutex);
{
if (_disposed) {
shouldDispose = YES;
} else {
#if RACCompoundDisposableInlineCount
for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) {
if (_inlineDisposables[i] == nil) {
_inlineDisposables[i] = disposable;
goto foundSlot;
}
}
#endif
if (_disposables == NULL)
_disposables = RACCreateDisposablesArray();
CFArrayAppendValue(_disposables, (__bridge void *)disposable);
if (RACCOMPOUNDDISPOSABLE_ADDED_ENABLED()) {
RACCOMPOUNDDISPOSABLE_ADDED(self.description.UTF8String, disposable.description.UTF8String, CFArrayGetCount(_disposables) + RACCompoundDisposableInlineCount);
}
#if RACCompoundDisposableInlineCount
foundSlot:;
#endif
}
}
pthread_mutex_unlock(&_mutex);
if (shouldDispose) [disposable dispose];
}
// 从RACCompoundDisposable管理集合中移除 RACDisposable
// 删除_inlineDisposables对应的disposable
- (void)removeDisposable:(RACDisposable *)disposable {
if (disposable == nil) return;
pthread_mutex_lock(&_mutex);
{
if (!_disposed) {
// 移除_inlineDisposables中的RACDisposable
#if RACCompoundDisposableInlineCount
for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) {
if (_inlineDisposables[i] == disposable)
_inlineDisposables[i] = nil;
}
#endif
// 移除_disposables中的RACDisposable
if (_disposables != NULL) {
CFIndex count = CFArrayGetCount(_disposables);
for (CFIndex i = count - 1; i >= 0; i--) {
const void *item = CFArrayGetValueAtIndex(_disposables, i);
if (item == (__bridge void *)disposable) {
CFArrayRemoveValueAtIndex(_disposables, i);
}
}
if (RACCOMPOUNDDISPOSABLE_REMOVED_ENABLED()) {
RACCOMPOUNDDISPOSABLE_REMOVED(self.description.UTF8String, disposable.description.UTF8String, CFArrayGetCount(_disposables) + RACCompoundDisposableInlineCount);
}
}
}
}
pthread_mutex_unlock(&_mutex);
}
// 对_disposables中的RACDisposable进行销毁
static void disposeEach(const void *value, void *context) {
RACDisposable *disposable = (__bridge id)value;
[disposable dispose];
}
// 遍历_inlineDisposables中的RACDisposable,进行销毁
// 如果_disposables中存在RACDisposable,也需要进行遍历,销毁
// 销毁的操作就是将原来的值置为nil
- (void)dispose {
#if RACCompoundDisposableInlineCount
RACDisposable *inlineCopy[RACCompoundDisposableInlineCount];
#endif
CFArrayRef remainingDisposables = NULL;
pthread_mutex_lock(&_mutex);
{
_disposed = YES;
#if RACCompoundDisposableInlineCount
for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) {
inlineCopy[i] = _inlineDisposables[i];
_inlineDisposables[i] = nil;
}
#endif
remainingDisposables = _disposables;
_disposables = NULL;
}
pthread_mutex_unlock(&_mutex);
// 对_inlineDisposables中的RACDisposable 进行销毁
#if RACCompoundDisposableInlineCount
for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) {
[inlineCopy[i] dispose];
}
#endif
if (remainingDisposables == NULL) return;
CFIndex count = CFArrayGetCount(remainingDisposables);
CFArrayApplyFunction(remainingDisposables, CFRangeMake(0, count), &disposeEach, NULL);
CFRelease(remainingDisposables);
}
#define RACCompoundDisposableInlineCount 2
RACCompoundDisposable
通过2种方式对RACDisposable
实例进行管理:
-
_inlineDisposables
:RACDisposable *_inlineDisposables[RACCompoundDisposableInlineCount]
,这是一种快捷方式,但是只能添加2个,一旦满了,就需要创建_disposables
这个数组来存储。对_inlineDisposables
的操作需要加锁。 -
_disposables
:CFMutableArrayRef _disposables
,这个数组是作为一个备用数组,当_inlineDisposables
存满了就需要使用这个数组来存储RACDisposable
。操作需要加锁。当_disposables
也存满了就需要将保存的disposable
销毁。
在上述例子,我们在销毁信号的地方设置一个断点,查看一下堆栈信息:
这也验证了我们上述的流程。
RACObserve
RACObserve
是对KVO
的封装,下面我们来看看其具体实现。
#define RACObserve(TARGET, KEYPATH) _RACObserve(TARGET, KEYPATH)
#define _RACObserve(TARGET, KEYPATH) \
({ \
__weak id target_ = (TARGET); \
[target_ rac_valuesForKeyPath:@keypath(TARGET, KEYPATH) observer:self]; \
})
- (RACSignal *)rac_valuesForKeyPath:(NSString *)keyPath observer:(__weak NSObject *)observer {
return [[[self
rac_valuesAndChangesForKeyPath:keyPath options:NSKeyValueObservingOptionInitial observer:observer]
map:^(RACTuple *value) {
return value[0];
}]
setNameWithFormat:@"RACObserve(%@, %@)", RACDescription(self), keyPath];
}
- (RACSignal *)rac_valuesAndChangesForKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options observer:(__weak NSObject *)weakObserver {
NSObject *strongObserver = weakObserver;
keyPath = [keyPath copy];
__weak NSObject *weakSelf = self;
// target的销毁信号,不再订阅信号
RACSignal *deallocSignal = [[RACSignal
zip:@[
self.rac_willDeallocSignal,
strongObserver.rac_willDeallocSignal ?: [RACSignal never]
]]
doCompleted:^{
......
}];
return [[[RACSignal
createSignal:^ RACDisposable * (id subscriber) {
......
// 观察者销毁 订阅者也发送完成信号
if (self == nil) {
[subscriber sendCompleted];
return nil;
}
return [self rac_observeKeyPath:keyPath options:options observer:observer block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
// 如果KVO检测到被观察者发生变化,则通过订阅者发送信号数据
[subscriber sendNext:RACTuplePack(value, change)];
}];
}]
// 销毁信号之后不再订阅信号
takeUntil:deallocSignal]];
}
- (RACDisposable *)rac_observeKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options observer:(__weak NSObject *)weakObserver block:(void (^)(id, NSDictionary *, BOOL, BOOL))block {
......
keyPath = [keyPath copy];
NSObject *strongObserver = weakObserver;
// 对keyPath的处理
NSArray *keyPathComponents = keyPath.rac_keyPathComponents;
BOOL keyPathHasOneComponent = (keyPathComponents.count == 1);
NSString *keyPathHead = keyPathComponents[0];
NSString *keyPathTail = keyPath.rac_keyPathByDeletingFirstKeyPathComponent;
// 初始化销毁者管理集合
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
BOOL shouldAddDeallocObserver = NO;
// 获取观察者的属性 这也就是为什么我们能在RACObserve()里面获取到响应属性的原因
objc_property_t property = class_getProperty(object_getClass(self), keyPathHead.UTF8String);
if (property != NULL) {
rac_propertyAttributes *attributes = rac_copyPropertyAttributes(property);
if (attributes != NULL) {
shouldAddDeallocObserver = isObject && isWeak && !isBlock && !isProtocol;
}
}
// dealloc观察者订阅信号的销毁操作
void (^addDeallocObserverToPropertyValue)(NSObject *) = ^(NSObject *value) {
.......
RACDisposable *deallocDisposable = [RACDisposable disposableWithBlock:^{
block(nil, change, YES, keyPathHasOneComponent);
}];
[valueDisposable addDisposable:deallocDisposable];
[firstComponentDisposable() addDisposable:[RACDisposable disposableWithBlock:^{
[valueDisposable removeDisposable:deallocDisposable];
}]];
};
// 将回调块添加到值的dealloc操作中,把清理回调的逻辑添加到销毁者
void (^addObserverToValue)(NSObject *) = ^(NSObject *value) {
RACDisposable *observerDisposable = [value rac_observeKeyPath:keyPathTail options:(options & ~NSKeyValueObservingOptionInitial) observer:weakObserver block:block];
[firstComponentDisposable() addDisposable:observerDisposable];
};
NSKeyValueObservingOptions trampolineOptions = (options | NSKeyValueObservingOptionPrior) & ~NSKeyValueObservingOptionInitial;
// 将观察的属性封装起来 进行观察
// RACKVOTrampoline 是KVO的观察者 一旦被dispose 观察就会停止
RACKVOTrampoline *trampoline = [[RACKVOTrampoline alloc] initWithTarget:self observer:strongObserver keyPath:keyPathHead options:trampolineOptions block:^(id trampolineTarget, id trampolineObserver, NSDictionary *change) {
// 观察者发生变化的回调
// 之后再通过sendNext的方式传给订阅者
......
block([value valueForKeyPath:keyPathTail], change, NO, keyPathHasOneComponent);
......
}];
// 当销毁trampoline的时候就停止KVO观察
[disposable addDisposable:trampoline];
// 如果需要的话 返回初始化的值
block(initialValue, initialChange, NO, keyPathHasOneComponent);
......
// 销毁对应的观察
return [RACDisposable disposableWithBlock:^{
[disposable dispose];
[observerDisposable removeDisposable:disposable];
[selfDisposable removeDisposable:disposable];
}];
}
// RACKVOTrampoline继承自RACDisposable,是一个KVO观察
// 将被观察者封装起来
- (instancetype)initWithTarget:(__weak NSObject *)target observer:(__weak NSObject *)observer keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(RACKVOBlock)block {
NSObject *strongTarget = target;
if (strongTarget == nil) return nil;
self = [super init];
// 保存观察的相关信息:keyPath、回调block、被观察者、观察者
_keyPath = [keyPath copy];
_block = [block copy];
_weakTarget = target;
_unsafeTarget = strongTarget;
_observer = observer;
// 使用中间代理层来响应KVO
// strongTarget 被观察对象
// RACKVOProxy.sharedProxy 观察者
// 在RACKVOProxy.sharedP内部维护一张NSMapTable 把所有的观察者都存在这个表里
[RACKVOProxy.sharedProxy addObserver:self forContext:(__bridge void *)self];
[strongTarget addObserver:RACKVOProxy.sharedProxy forKeyPath:self.keyPath options:options context:(__bridge void *)self];
[strongTarget.rac_deallocDisposable addDisposable:self];
[self.observer.rac_deallocDisposable addDisposable:self];
return self;
}
// 响应KVO,被观察者变化的回调
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
RACKVOBlock block;
id observer;
id target;
@synchronized (self) {
block = self.block;
observer = self.observer;
target = self.weakTarget;
}
if (block == nil || target == nil) return;
// 观察到被观察者变化的回调block
block(target, observer, change);
}
- (void)dispose {
NSObject *target;
NSObject *observer;
@synchronized (self) {
_block = nil;
target = self.unsafeTarget;
observer = self.observer;
_unsafeTarget = nil;
_observer = nil;
}
[target.rac_deallocDisposable removeDisposable:self];
[observer.rac_deallocDisposable removeDisposable:self];
// 以下两步就确定了RACKVO不需要手动移除观察者
// 移除中间层的观察
[target removeObserver:RACKVOProxy.sharedProxy forKeyPath:self.keyPath context:(__bridge void *)self];
// 中间层移除观察者
[RACKVOProxy.sharedProxy removeObserver:self forContext:(__bridge void *)self];
}
总结一下:
-
RACObserve
是封装的一个宏定义,这个宏定义的实现在NSObject
的一个名为RACPropertySubscribing
的分类, - 在
RACPropertySubscribing
中主要的处理:- 当收到释放订阅观察的信号就不再订阅、
- 当前类被销毁的时候,订阅者发送完成的信号
- 进入
NSObject
的RACKVOWrapper
分类中,主要处理如下:- 对
keyPath
的处理,比如二级路由等 - 初始化
RACCompoundDisposable
管理销毁者 - 获取观察者的属性
- 处理一些关于
dealloc
的销毁操作
- 对
- 进入
RACKVOTrampoline
这个类:- 包装观察需要的相关属性
- 使用中间层
RACKVOProxy
来观察被观察的对象,而不是直接使用观察者,将观察者保存在RACKVOProxy
中 -
RACKVOTrampoline
被释放的时候,移除观察者 - 回调给外界观察者发生的变化
-
RACKVOProxy
:中间层,充当观察者- 维护一张表
NSMapTable
来保存原来的观察者 - 响应系统被观察者发生变化的回调
- 维护一张表
被观察者的变化则是通过订阅者发送给外界:
[subscriber sendNext:RACTuplePack(value, change)]
移除观察者的流程则是当观察者被销毁的时候,就会销毁相关的临时变量,也就是观察的销毁者等,这样就会调用到RACKVOTrampoline
这个类的dispose
方法,移除观察者。
RACSubject
RACSubject
可以看做是一种可以手动控制发送next, completed, and error
的信号,对桥接RAC
和非RAC
很有帮助。它RACSignal
的子类,还实现了RACSubscriber
协议。
它有以下特点:
- 能够手动发送事件
- 能够订阅信号
那么,它是如何做到又能发送信号,又能订阅信号的呢?我们来看看它的内部实现。
@property (nonatomic, strong, readonly) NSMutableArray *subscribers;
@property (nonatomic, strong, readonly) RACCompoundDisposable *disposable;
+ (instancetype)subject {
return [[self alloc] init];
}
- (instancetype)init {
self = [super init];
if (self == nil) return nil;
_disposable = [RACCompoundDisposable compoundDisposable];
_subscribers = [[NSMutableArray alloc] initWithCapacity:1];
return self;
}
它的内部维护了一个销毁者集合和一个订阅者数组。这个订阅者的数组就是实现订阅的关键。
外部调用订阅方法的时候,就会把生成的订阅者存放在_subscribers
这个数组里面。
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
- (RACDisposable *)subscribe:(id)subscriber {
NSCParameterAssert(subscriber != nil);
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
// 生成订阅者
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
// 添加订阅者 保存
NSMutableArray *subscribers = self.subscribers;
@synchronized (subscribers) {
[subscribers addObject:subscriber];
}
// 销毁者销毁订阅者
[disposable addDisposable:[RACDisposable disposableWithBlock:^{
@synchronized (subscribers) {
NSUInteger index = [subscribers indexOfObjectWithOptions:NSEnumerationReverse passingTest:^ BOOL (id obj, NSUInteger index, BOOL *stop) {
return obj == subscriber;
}];
if (index != NSNotFound) [subscribers removeObjectAtIndex:index];
}
}]];
return disposable;
}
当外部调用sendNext
发送信号的方法时,它会遍历之前存放的_subscribers
数组,一一回调执行每个订阅者的sendNext
方法。
- (void)sendNext:(id)value {
[self enumerateSubscribersUsingBlock:^(id subscriber) {
[subscriber sendNext:value];
}];
}
- (void)enumerateSubscribersUsingBlock:(void (^)(id subscriber))block {
NSArray *subscribers;
@synchronized (self.subscribers) {
subscribers = [self.subscribers copy];
}
// 遍历订阅者列表 回调
for (id subscriber in subscribers) {
block(subscriber);
}
}
由于RACSubject
响应信号的时候时候是遍历订阅者,一一响应,那么我们可以得出多个订阅者订阅同一个信号,响应的时候不需要多次发送信号消息。
RACMulticastConnection
RACMulticastConnection
,多播信号,用于将一个信号发送给多个订阅者。通俗的说,就是多个订阅者都订阅了一个信号,当这个信号发出消息的时候,每个订阅者都会收到,而不需要单独的给每个订阅者都发送一次消息。调用了-[RACMulticastConnection connect]
方法才会开始订阅多播信号。RACMulticastConnection
不应该手动创建,而是通过-[RACSignal publish]
或者-[RACSignal multicast:]
方法创建。
- (RACMulticastConnection *)publish {
// 在内部会生成一个手动信号
RACSubject *subject = [[RACSubject subject] setNameWithFormat:@"[%@] -publish", self.name];
RACMulticastConnection *connection = [self multicast:subject];
return connection;
}
- (RACMulticastConnection *)multicast:(RACSubject *)subject {
[subject setNameWithFormat:@"[%@] -multicast: %@", self.name, subject.name];
RACMulticastConnection *connection = [[RACMulticastConnection alloc] initWithSourceSignal:self subject:subject];
return connection;
}
- (instancetype)initWithSourceSignal:(RACSignal *)source subject:(RACSubject *)subject {
NSCParameterAssert(source != nil);
NSCParameterAssert(subject != nil);
self = [super init];
_sourceSignal = source; // 原信号
_serialDisposable = [[RACSerialDisposable alloc] init];
_signal = subject; // 新建的手动信号
return self;
}
我们再来看看RACMulticastConnection
和RACSignal
的区别:
RACMulticastConnection
发送:
RACSignal
发送:
同一个信号给多个订阅者发送信息的时候,RACMulticastConnection
只需要发送一次,所有订阅者都会响应;而RACSignal
则需要给每个订阅者都发送一次。例子中的connection.signal
其实已经是内部创建的RACSubject
,而RACSubject
订阅信号的时候是把订阅者都放在一个数组里,响应信号的时候则是遍历这个数组挨个响应,就不需要我们一一发信号了。
RACCommand
RACCommand
是响应某些动作(通常与UI相关)而触发的信号。在用于与UIKit
组件进行交互时,RACCommand
能够帮助我们更快的处理并且响应任务,减少编码以及工程的复杂度。
我们先来看一个RACCommand
的例子:
executionSignals
中发送了新的信号时,switchToLatest
方法返回的信号都会订阅这个最新的信号,这里也就保证了每次都会打印出最新的信号中的值。executing
用来监听是否正在执行中,当执行开始后会置为1、执行结束之后置为0。
那么RACCommand
是如何实现订阅信号的呢?在其内部维护了一个RACSubject *addedExecutionSignalsSubject
的对象,通过这个对象,它可以将信号的变化发给订阅者。
- (RACSignal *)execute:(id)input {
......
RACSignal *signal = self.signalBlock(input);
// 多播信号发送信号给订阅者
RACMulticastConnection *connection = [[signal
subscribeOn:RACScheduler.mainThreadScheduler]
multicast:[RACReplaySubject subject]];
[self.addedExecutionSignalsSubject sendNext:connection.signal];
[connection connect];
return [connection.signal setNameWithFormat:@"%@ -execute: %@", self, RACDescription(input)];
}
RACCommand
在初始化的时候维护了很多关于信号的状态,而这些状态可以帮助我们判断信号的情况。
- (instancetype)initWithSignalBlock:(RACSignal * (^)(id input))signalBlock {
return [self initWithEnabled:nil signalBlock:signalBlock];
}
- (instancetype)initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal * (^)(id input))signalBlock {
NSCParameterAssert(signalBlock != nil);
self = [super init];
_addedExecutionSignalsSubject = [RACSubject new];
_allowsConcurrentExecutionSubject = [RACSubject new];
_signalBlock = [signalBlock copy];
// 包含信号的信号
// 在每次执行 -execute: 方法时,最终都会向 executionSignals 中传入一个最新的信号
_executionSignals = ......;
// errorsConnection 发生错误的多播信号
RACMulticastConnection *errorsConnection = ......;
// immediateExecuting 是一个用于表示当前是否有任务执行的信号
RACSignal *immediateExecuting = ......;
// _executing是否正在执行
_executing = ......;
// moreExecutionsAllowed 是否允许更多操作执行的信号
RACSignal *moreExecutionsAllowed = ......;
// 在每次原信号发送消息时都会重新计算
_immediateEnabled = ......;
// 是否可以再次执行
_enabled = ......;
return self;
}
总结
-
RACPassthroughSubscriber
类,就是用来订阅信号、发送信号任务的。 -
RACScheduler
类,封装GCD
,让信号任务同步执行。 -
RACDisposable
类,销毁者,取消订阅,销毁订阅信号操作中间生成的一些辅助销毁对象。 -
RACCompoundDisposable
继承自RACDisposable
,是销毁者集合,它通过_inlineDisposables
和_disposables
管理着一个或者多个RACDisposable
。 -
RACObserve
:封装系统的KVO
,使用RACKVOTrampoline
将观察的相关信息封装起来,使用中间层RACKVOProxy
作为观察者来进行观察,将原来的观察者维护在NSMapTable
表中,当观察到对象发生变化时,RACKVOTrampoline
通过回调通知RACKVOWrapper
类,然后以发送信号的方式,通知外界。移除观察也在RACKVOTrampoline
中进行处理。 -
RACSubject
:订阅信号的时候,将生成的RACPassthroughSubscriber
订阅者存在_subscribers
数组里;发送信号的时候,遍历数组,一一发放。 -
RACMulticastConnection
,多播信号,用于将信号发送给多个订阅者。与RACSignal
不同的是,它只需要发送一次,所有订阅者都会收到。 -
RACCommand
用于表示事件的执行,多用于响应UI
上的某些动作。