美文网首页
RACDisposable

RACDisposable

作者: boy丿log | 来源:发表于2019-04-03 16:10 被阅读0次

    RACDisposable

    rac中用来销毁订阅者的类。其有4个子类:

    • RACCompoundDisposable:它可以包含多个 disposable 对象,并且支持手动添加和移除 disposable 对象
    • RACKVOTrampoline: 代表一次 KVO 观察,并且可以用来停止观察
    • RACScopedDisposable:当它被 dealloc 的时候调用本身的 -dispose 方法
    • RACSerialDisposable:作为 disposable 的容器使用,可以包含一个 disposable 对象,并且允许将这个 disposable 对象通过原子操作交换出来

    父类RACDisposable,相当于一次性任务

    在初始化RACSignal子类的时候block会返回一个RACDisposable对象

    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            [subscriber sendNext:@"111"];
            return [RACDisposable disposableWithBlock:^{
                NSLog(@"1");
            }];
        }];
    

    就是这个return nil。 在信号被销毁的时候会打印:1。

    RACDisposable的.h如下:

    @interface RACDisposable : NSObject
    
    //只读属性,用来判断是否已经释放
    @property (atomic, assign, getter = isDisposed, readonly) BOOL disposed;
    
    //初始化方法
    + (instancetype)disposableWithBlock:(void (^)(void))block;
    
    //手动销毁
    - (void)dispose;
    
    //返回一个RACScopedDisposable对象,更换作用域
    - (RACScopedDisposable *)asScopedDisposable;
    
    @end
    

    .m文件最重要实现是:

    - (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();
        }
    

    其中:
    OSMemoryBarrier:是汇编层面的一个的一个方法,就是用来设置内存屏障,它即可以用于读操作,也可以用于写操作。
    CFBridgingRetain:将一个OC对象转为非ARC对象并交出内存管理的能力。
    CFBridgingRelease:讲一个非ARC对象转换为一个非ARC的对象。
    OSAtomicCompareAndSwapPtrBarrier:比较两个地址是否相同

    这段代码的作用是,首先,创建一个disposeBlock的block对象,该函数会判断 blockPtr 所指向的地址是否与 &__ disposeBlock 内存地址中存储的指针地址相同,若相同,则将 NULL 保存到 &_disposeBlock 内存地址中。

    即当 blockPtr == *(&_disposeBlock) 为 YES 时,并且 blockPtr 并不是指向 self 时,则其所指向的代码块便会被执行,执行完毕后,代码块即可被释放。

    RACCompoundDisposable,多个任务

    RACCompoundDisposable可以添加多个RACDisposable任务,.h文件如下:

    //初始化一个空的RACCompoundDisposable对象
    + (instancetype)compoundDisposable;
    //初始化时添加一个的Disposable数组
    + (instancetype)compoundDisposableWithDisposables:(nullable NSArray *)disposables;
    
    //添加
    - (void)addDisposable:(nullable RACDisposable *)disposable;
    //删除
    - (void)removeDisposable:(nullable RACDisposable *)disposable;
    
    @end
    

    RACCompoundDisposable中创建了

    RACDisposable *_inlineDisposables[RACCompoundDisposableInlineCount];
    
    CFMutableArrayRef _disposables;
    
    

    在只聚合两个的时候用C数组,在大于两个的时候将后面两个添加到foundation数组中

    具体分析见ReactiveCocoa学习笔记六-RACDisposable源码分析

    RACSerialDisposable,可以用来交换未处理任务

    先来看下头文件:

    @interface RACSerialDisposable : RACDisposable
    
    //当前持有的任务
    @property (atomic, strong, nullable) RACDisposable *disposable;
    
    //通过一个任务初始化一个任务
    + (instancetype)serialDisposableWithDisposable:(nullable RACDisposable *)disposable;
    
    //交换一个未处理的任务,如果处理过了那么新的任务会立刻进入完成状态
    {
    if (alreadyDisposed) {
            [newDisposable dispose];
            return nil;
        }}返回的是老的信号
    
    - (nullable RACDisposable *)swapInDisposable:(nullable RACDisposable *)newDisposable;
    
    @end
    

    RACScopedDisposable,包装了一层,与父类的区别是在dealloc的时候回自动调用dispose

    RACKVOTrampoline

    这个类是用在观察模式中,在介绍之前先介绍两个文件:

    • NSObject+RACDeallocating
    • RACKVOProxy

    第一个文件,是为了给NSObject添加一个replay信号,其实现了dealloc的方法交换,在Object销毁时会自动调用信号的销毁。

    //销毁前执行的任务
    @property (atomic, readonly, strong) RACCompoundDisposable *rac_deallocDisposable;
    
    //一个监听销毁的信号
    - (RACSignal *)rac_willDeallocSignal;
    
    id newDealloc = ^(__unsafe_unretained id self) {
    RACCompoundDisposable *compoundDisposable = objc_getAssociatedObject(self, RACObjectCompoundDisposable);
    [compoundDisposable dispose];
    
    if (originalDealloc == NULL) {
        struct objc_super superInfo = {
                      .receiver = self,
                        .super_class = class_getSuperclass(classToSwizzle)
       };
    
    void (*msgSend)(struct objc_super *, SEL) = (__typeof__(msgSend))objc_msgSendSuper;
                    msgSend(&superInfo, deallocSelector);
                } else {
                    originalDealloc(self, deallocSelector);
                }
            };
    

    第二个文件,只是对kvo观察者及keypath的管理。

    @interface RACKVOProxy : NSObject
    
    //单例
    + (instancetype)sharedProxy;
    
    //添加观察者
    - (void)addObserver:(__weak NSObject *)observer forContext:(void *)context;
    
    //移除观察者
    - (void)removeObserver:(NSObject *)observer forContext:(void *)context;
    
    @end
    
    

    里面使用NSMapTable实现的
    RACKVOTrampoline 这个类.h只有一个初始化方法

    //
    // target   - 观察者目标
    // observer -观察者,可以为nil
    // keyPath  - 观察路径,可以为nil
    // options  - 观察选项
    // block    - 回调
    
    /
    - (instancetype)initWithTarget:(__weak NSObject *)target observer:(__weak NSObject *)observer keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(RACKVOBlock)block;
    

    接下来,我们看下.m的实现:

    - (instancetype)initWithTarget:(__weak NSObject *)target observer:(__weak NSObject *)observer keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(RACKVOBlock)block {
        NSCParameterAssert(keyPath != nil);
        NSCParameterAssert(block != nil);
    
        NSObject *strongTarget = target;
        if (strongTarget == nil) return nil;
    
        self = [super init];
       //赋值
        _keyPath = [keyPath copy];
       
        _block = [block copy];
        _weakTarget = target;
        _unsafeTarget = strongTarget;
        _observer = observer;
       
       //将监听对象和key值一对一添加到RACKVOProxy的但李忠
        [RACKVOProxy.sharedProxy addObserver:self forContext:(__bridge void *)self];
        //RACKVOProxy添加对监听对象的监听
        [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;
    }
    
    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];
        //移除监听和map
        [target removeObserver:RACKVOProxy.sharedProxy forKeyPath:self.keyPath context:(__bridge void *)self];
        [RACKVOProxy.sharedProxy removeObserver:self forContext:(__bridge void *)self];
    

    相关文章

      网友评论

          本文标题:RACDisposable

          本文链接:https://www.haomeiwen.com/subject/lgyzbqtx.html