美文网首页
RxSwift-deallocating,deallocated

RxSwift-deallocating,deallocated

作者: king_jensen | 来源:发表于2019-08-10 18:16 被阅读0次

    deallocating,deallocated的使用

    我们通常将deallocating序列结合takeUntil使用。达到当对象销毁时,序列会自动销毁的目的。

      let vc = LGDetialViewController()
            _ = vc.publicOB
                .takeUntil(vc.rx.deallocating)
            .subscribe(onNext: { (item) in
                print("订阅到 \(item)")
            })
            self.navigationController?.pushViewController(vc, animated: true)
    

    本文对deallocating序列源码进行解析,了解RxSwift是如何监控一个对象的释放,并给订阅者发送消息的。

    deallocating源码解析

    想要精确知道一个对象的是否销毁,那就必须掌握对象dealloc方法是否执行。掌握dealloc方法是否执行,很容易就想到runtime的方法交换。RxSwift也是通过方法交换的方式实现的吗?我们进入源码一探究竟。

    private let deallocSelector = NSSelectorFromString("dealloc")
       public var deallocating: Observable<()> {
            return self.synchronized {
                do {
                    let proxy: DeallocatingProxy = try self.registerMessageInterceptor(deallocSelector)
                    return proxy.messageSent.asObservable()
                }
                catch let e {
                    return Observable.error(e)
                }
            }
        }
    

    首先调用registerMessageInterceptor创建DeallocatingProxy对象. 参数是deallocSelector
    dealloc在ARC下不允许直接@seleteror(dealloc),采用NSSelectorFromString("dealloc")方式解决。

      fileprivate func registerMessageInterceptor<T: MessageInterceptorSubject>(_ selector: Selector) throws -> T {
           ......
           var error: NSError?
            let targetImplementation = RX_ensure_observing(self.base, selector, &error)
            if targetImplementation == nil {
                throw error?.rxCocoaErrorForTarget(self.base) ?? RxCocoaError.unknown
            }
    
            subject.targetImplementation = targetImplementation!
    
            return subject
        }
    

    通过方法名称,我们推测RX_ensure_observing应该是我们要分析的重要方法。

    IMP __nullable RX_ensure_observing(id __nonnull target, SEL __nonnull selector, NSErrorParam error) {
        __block IMP targetImplementation = nil;
        // Target is the second object that needs to be synchronized to TRY to make sure other swizzling framework
        // won't do something in parallel.
        // Even though this is too fine grained locking and more coarse grained locks should exist, this is just in case
        // someone calls this method directly without any external lock.
        @synchronized(target) {
            // The only other resource that all other swizzling libraries have in common without introducing external
            // dependencies is class object.
            //
            // It is polite to try to synchronize it in hope other unknown entities will also attempt to do so.
            // It's like trying to figure out how to communicate with aliens without actually communicating,
            // save for the fact that aliens are people, programmers, authors of swizzling libraries.
            @synchronized([target class]) {
                [[RXObjCRuntime instance] performLocked:^(RXObjCRuntime * __nonnull self) {
                    targetImplementation = [self ensurePrepared:target
                                                   forObserving:selector
                                                          error:error];
                }];
            }
        }
    
        return targetImplementation;
    }
    

    进入方法-(IMP __nullable)ensurePrepared:(id __nonnull)target forObserving:(SEL __nonnull)selector error:(NSErrorParam)error
    经过查找,我们找到下面的关键代码

     if (![self swizzleDeallocating:deallocSwizzingTarget error:error]) {
                return nil;
            }
    
    SWIZZLE_INFRASTRUCTURE_METHOD(
        void,
        swizzleDeallocating,
        ,
        deallocSelector,
        DEALLOCATING_BODY
    )
    

    这个方法用宏实现的。Swift下没有Load方法,使用宏定义预编译。使用宏可以获得更高的代码运行效率。
    把这个宏还原成下列方法:

        - (BOOL)swizzleDeallocating:(Class __nonnull)class error:(NSErrorParam)error
            {
                SEL selector = deallocSelector;
            
            __unused SEL rxSelector = RX_selector(selector);
            IMP (^newImplementationGenerator)(void) = ^() {
            __block IMP thisIMP = nil;
            id newImplementation = ^void(__unsafe_unretained id self         DECLARE_ARGUMENTS(__VA_ARGS__)) {
            DEALLOCATING_BODY(__VA_ARGS__)
            
            struct objc_super superInfo = {
            .receiver = self,
            .super_class = class_getSuperclass(class)
            };
            
            void (*msgSend)(struct objc_super *, SEL DECLARE_ARGUMENTS(__VA_ARGS__))
            = (__typeof__(msgSend))objc_msgSendSuper;
            @try {
            return msgSend(&superInfo, selector ARGUMENTS(__VA_ARGS__));
            }
            @finally { NO_BODY(__VA_ARGS__) }
            };
            
            thisIMP = imp_implementationWithBlock(newImplementation);
            return thisIMP;
            };
            
            IMP (^replacementImplementationGenerator)(IMP) = ^(IMP originalImplementation) {
            __block void (*originalImplementationTyped)(__unsafe_unretained id, SEL DECLARE_ARGUMENTS(__VA_ARGS__) )
            = (__typeof__(originalImplementationTyped))(originalImplementation);
            
            __block IMP thisIMP = nil;
            id implementationReplacement = ^void(__unsafe_unretained id self DECLARE_ARGUMENTS(__VA_ARGS__) ) {
            DEALLOCATING_BODY(__VA_ARGS__)
            @try {
            return originalImplementationTyped(self, selector ARGUMENTS(__VA_ARGS__));
            }
            @finally { NO_BODY(__VA_ARGS__) }
            };
            
            thisIMP = imp_implementationWithBlock(implementationReplacement);
            return thisIMP;
            };
            
            return [self ensureSwizzledSelector:selector
            ofClass:class
            newImplementationGenerator:newImplementationGenerator
            replacementImplementationGenerator:replacementImplementationGenerator
            error:error];
            }
    

    进入-(BOOL)ensureSwizzledSelector:(SEL __nonnull)selector ofClass:(Class __nonnull)class newImplementationGenerator:(IMP(^)(void))newImplementationGenerator replacementImplementationGenerator:(IMP (^)(IMP originalImplementation))replacementImplementationGenerator error:(NSErrorParam)error方法

     IMP originalImplementation = method_getImplementation(existingMethodOnTargetClass);
      
        IMP implementationReplacementIMP = replacementImplementationGenerator(originalImplementation);
    
        IMP originalImplementationAfterChange = method_setImplementation(existingMethodOnTargetClass, implementationReplacementIMP);
    

    代码中通过method_getImplementation获取dealloc当前的IMP originalImplementation
    然后获取要替换的IMPimplementationReplacementIMP,然后使用method_setImplementationexistingMethodOnTargetClassMethod设置新的IMP。

    到目前为止,我们已经验证deallocating序列是通过runtime的方式为交换delloc的实现,从而实现对对象释放的监控。
    当对象调用dealloc方法,会进入replacementImplementationGenerator这个IMP

       IMP (^replacementImplementationGenerator)(IMP) = ^(IMP originalImplementation) {
            __block void (*originalImplementationTyped)(__unsafe_unretained id, SEL DECLARE_ARGUMENTS(__VA_ARGS__) )
            = (__typeof__(originalImplementationTyped))(originalImplementation);
            
            __block IMP thisIMP = nil;
            id implementationReplacement = ^void(__unsafe_unretained id self DECLARE_ARGUMENTS(__VA_ARGS__) ) {
            DEALLOCATING_BODY(__VA_ARGS__)
            @try {
            return originalImplementationTyped(self, selector ARGUMENTS(__VA_ARGS__));
            }
            @finally { NO_BODY(__VA_ARGS__) }
            };
            
            thisIMP = imp_implementationWithBlock(implementationReplacement);
            return thisIMP;
            };
    

    IMP中先执行DEALLOCATING_BODY(__VA_ARGS__),然后调用dealloc交换前的IMP.
    DEALLOCATING_BODY也是宏实现的

    #define DEALLOCATING_BODY(...)                                                        \
        id<RXDeallocatingObserver> observer = objc_getAssociatedObject(self, rxSelector); \
        if (observer != nil && observer.targetImplementation == thisIMP) {                \
            [observer deallocating];                                                      \
        }
    

    代码中调用[observer deallocating],观察者是关联属性rxSelector,我们追溯到registerMessageInterceptor方法中, 知道序列的观察者是DeallocatingProxy
    那么[observer deallocating]会来到DeallocatingProxy. deallocating()

    @objc func deallocating() {
                self.messageSent.on(.next(()))
            }
    

    DeallocatingProxy中保存ReplaySubject序列

      let messageSent = ReplaySubject<()>.create(bufferSize: 1)
    

    DeallocatingProxy.deallocating()中对messageSent序列发送响应。
    发送响应后,那么就会有订阅者来接收。由于deallocatingtakeUntil经常结合起来使用,那么分析一下takeUntil的源码,探索一下takeUntil内部是如何接收deallocating发送的响应非常有必要。想要了解takeUntil源码,请查阅RxSwift-TakeUntil源码分析

    至此,deallocating的源码分析已经完成,deallocated的实现与deallocating基本一致,这里就不再赘述了。

    总结:

    1.创建序列messageSent,返回到外界。
    2.通过method-swizzing监控对象的dealloc
    3.当调用对象的dealloc,为messageSent发送响应.

    deallocating.png

    相关文章

      网友评论

          本文标题:RxSwift-deallocating,deallocated

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