这部分主要分析下RACDisposable对象。还是上次的代码,只不过上次在创建信号的block中我们返回了nil,这次返回一个RACDisposable对象。
//1、创建信号量
RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"创建信号量");
//3、发布信息
[subscriber sendNext:@"I'm send next data"];
NSLog(@"那我啥时候运行");
return [RACDisposable disposableWithBlock:^{
NSLog(@"disposable");
}];
}];
//2、订阅信号量
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
到disposableWithBlock方法里面看看,创建了RACDisposable对象,用这个block做了初始化(把这个block保存到_disposeBlock属性里)。
+ (instancetype)disposableWithBlock:(void (^)(void))block {
return [[self alloc] initWithBlock:block];
}
- (instancetype)initWithBlock:(void (^)(void))block {
NSCParameterAssert(block != nil);
self = [super init];
_disposeBlock = (void *)CFBridgingRetain([block copy]);
OSMemoryBarrier();
return self;
}
那这个block什么时候会被调用呢?
1 订阅者被销毁
2 RACDisposable 调用dispose取消订阅
第一种情况,如果我们强引用这个subscriber,这个block不会被调用。
先添加一个属性
@property (strong,nonatomic) id<RACSubscriber> subscriber;
//1、创建信号量
RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"创建信号量");
//3、发布信息
[subscriber sendNext:@"I'm send next data"];
self.subscriber = subscriber; //强引用
NSLog(@"那我啥时候运行");
return [RACDisposable disposableWithBlock:^{
NSLog(@"disposable");
}];
}];
//2、订阅信号量
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
这个时候就不会输出disposable。说明打印disposable的block也没有被调用。
下面通过代码分析下为什么会这样。上一讲里面说过subscribeNext:方法里面会生成一个RACSubscriber对象,并且会调用生成信号的时候传递过来的bloc(以RACSubscriber对象作为block参数),这个block会被执行,打印了"创建信号量"等字符串。这个block以RACSubscriber对象作为参数(其实满足RACSubscriber协议就行,这里RACSubscriber类就满足RACSubscriber协议),返回RACDisposable类型的对象。创建RACDisposable对象的时候传递了一个block,这个block为什么在订阅者subscriber销毁的时候被调用呢。我们继续看代码
RACSubscriber.m
- (void)dealloc {
[self.disposable dispose];
}
在订阅者被销毁的时候,会调用订阅者持有的disposable对象的dispose方法。
- (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();
}
最终还是调用了创建RACDisposable对象的时候传入的block,所以就打印了“ disposable”。
第二种情况是直接调用了这个dispose方法,也会执行创建RACDisposable对象的时候传入的block,所以就打印了“ disposable”。
网友评论