RACDisposable
RACDisposable 是 ReactiveCocoa 中十分常见的类,其封装了注销订阅者时所要做的工作。
该类的方法十分简单,一个用来创建实例,封装要做的操作,一个执行操作。
+ (instancetype)disposableWithBlock:(void (^)(void))block;
- (void)dispose;
在该类中,有一个实例变量 _disposeBlock ,其是默认指向 self 的指针,在初始化后,其指向待执行的代码块。
- (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;
}
}
if (disposeBlock != nil) disposeBlock();
}
在 dispose 方法中,会调用 OSAtomicCompareAndSwapPtrBarrier() 函数,该函数会判断 blockPtr 所指向的地址是否与 &_disposeBlock 内存地址中存储的指针地址相同,若相同,则将 NULL 保存到 &_disposeBlock 内存地址中。
即当 blockPtr == *(&_disposeBlock) 为 YES 时,并且 blockPtr 并不是指向 self 时,则其所指向的代码块便会被执行,执行完毕后,代码块即可被释放。
RACCompoundDisposable
RACCompoundDisposable 是 RACDisposable 的子类,其可以包含多个 RACDisposable 实例,用来保存多个待处理的任务。
为了更快的访问待处理的任务,在该类中声明了一个 _inlineDisposables 指针,其指向一个包含有 RACCompoundDisposableInlineCount 个 RACDisposable 实例的数组,该值默认为 2 ,当添加的任务超过该值时,便会创建额外的数组进行保存。
#if RACCompoundDisposableInlineCount
RACDisposable *_inlineDisposables[RACCompoundDisposableInlineCount];
#endif
CFMutableArrayRef _disposables;
该类提供了两个创建实例的类方法:
+ (instancetype)compoundDisposable;
+ (instancetype)compoundDisposableWithDisposables:(nullable NSArray *)disposables;
得到实例对象后,可以调用下面的方法添加任务,如果当前组合任务已经被执行了,那么待添加的任务也会立刻执行。
- (void)addDisposable:(nullable RACDisposable *)disposable;
无论组合的任务处于什么状态,都可以调用下面的方法移除指定的任务,如果任务不存在,那么则直接返回。
- (void)removeDisposable:(nullable RACDisposable *)disposable;
该类还重写了 dispose 方法,调用时,该类实例会调用自身所包含的所有任务的 dispose 方法。
这些方法的执行都是线程安全的,因为该类声明了一个变量锁,保证其线程安全性。
pthread_mutex_t _mutex;
const int result __attribute__((unused)) = pthread_mutex_init(&_mutex, NULL);
所有要求线程安全的代码都包含在锁中:
pthread_mutex_lock(&_mutex);
{
//代码
}
pthread_mutex_unlock(&_mutex);
RACScopedDisposable
RACScopedDisposable 是 RACDisposable 的子类,其同父类的区别在于其被释放时,在 dealloc 方法中会调用 dispose 方法。
从该类的实例创建方法可知,该类通常是将 RACDisposable 的实例进行封装。
+ (instancetype)scopedDisposableWithDisposable:(RACDisposable *)disposable {
return [self disposableWithBlock:^{
[disposable dispose];
}];
}
RACDisposable 实例对象可以直接调用 asScopedDisposable 实例方法获取一个该类的实例对象。
RACKVOTrampoline
RACKVOTrampoline 是 RACDisposable 的子类,该类将监听目标属性变化的任务进行了封装,当 dispose 方法调用时,便结束该监听任务。
typedef void (^RACKVOBlock)(id target, id observer, NSDictionary *change);
- (instancetype)initWithTarget:(__weak NSObject *)target observer:(__weak NSObject *)observer keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(RACKVOBlock)block;
RACSerialDisposable
RACSerialDisposable 是 RACDisposable 的子类,该类提供的类方法和实例方法都是针对属性 disposable 的,实际上该类所持有的任务都是存储在 disposable 属性中的。
@property (atomic, strong, nullable) RACDisposable *disposable;
+ (instancetype)serialDisposableWithDisposable:(nullable RACDisposable *)disposable;
//使用新任务替换原任务,如果任务已经执行完毕,那么新任务 newDisposable 立刻执行,
//并且保持属性 disposable 为 nil
- (nullable RACDisposable *)swapInDisposable:(nullable RACDisposable *)newDisposable;
并且,该类重写了 initWithBlock: 方法,将任务封装在了属性 disposable 中。
- (instancetype)initWithBlock:(void (^)(void))block {
self = [self init];
if (self == nil) return nil;
self.disposable = [RACDisposable disposableWithBlock:block];
return self;
}