美文网首页
RxSwift-中介者模式&deallocating

RxSwift-中介者模式&deallocating

作者: 小强_123 | 来源:发表于2019-08-12 00:21 被阅读0次

    我们先由timer的创建使用,引出中介者模式,进而扩展介绍Rxswift的中介者模式使用。

    首先,我们来看timer的几种创建方式如下:

    1.常用的timer创建,加入到runloop中

    let timer = Timer.init(timeInterval: 1, target: self, selector: #selector(timerFire), userInfo: nibName, repeats: true)
    RunLoop.current.add(timer, forMode: .common)
    

    2.CADisplayLink

    let displayLink = CADisplayLink(target: self, selector: #selector(timerFire))
    displayLink.preferredFramesPerSecond = 1
    displayLink.add(to: RunLoop.current, forMode: .default)
    

    3.GCDTimer

    gcdTimer = DispatchSource.makeTimerSource()
    gcdTimer?.schedule(deadline: DispatchTime.now(), repeating: DispatchTimeInterval.seconds(1))
    gcdTimer?.setEventHandler(handler: {
        print("hello GCD")
    })
    gcdTimer?.resume()
    

    4.RxSwift的timer

    timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
            _ = observable?.subscribe(onNext:{(number) in
                
            }).disposed(by: disposeBag)
    

    注意: 1,2的创建方式需要加入到runloop中,runloopMode指定为default时,UI操作会影响计时准确度,runloopMode指定为.common时,不受UI操作影响。

    使用第一种方式创建timer时,如果需要self持有timer进行其他操作时,就会形成循环引用,因为在初始化时,将self作为target传值给timer,而self又持有timer。

    下面我们将使用中介者模式来规避这个循环引用的问题
    创建一个XQProxy类,如下

    class XQProxy: NSObject {
        weak var target : NSObjectProtocol?
        var sel : Selector?
        var xqTimer : Timer?
        
        override init() {
            super.init()
        }
        
        func xq_scheduleTimer(timeInterval interval:TimeInterval ,target  innerTagert:Any ,selector aselector:Selector , userInfo :Any? , repeat yesOrNo:Bool) {
            self.target = innerTagert as? NSObjectProtocol
            self.sel = aselector
            self.xqTimer = Timer.init(timeInterval: interval, target: self, selector: aselector, userInfo: userInfo, repeats: yesOrNo)
            RunLoop.current.add(self.xqTimer!, forMode: .common)
            
            guard self.target?.responds(to: self.sel)==true else {
                return
            }
            
            let method = class_getInstanceMethod(self.classForCoder, #selector(xq_timerFire))
            class_replaceMethod(self.classForCoder, self.sel!, method_getImplementation(method!), method_getTypeEncoding(method!))
        }
        
        @objc fileprivate func xq_timerFire () {
            if self.target != nil {
                self.target!.perform(self.sel)
            }else{
                self.xqTimer?.invalidate()
                self.xqTimer = nil
            }
        }
    }
    

    外部调用代码如下,即可开启定时任务

    xqProxy.xq_scheduleTimer(timeInterval: 1, target: self, selector: #selector(timerFunc), userInfo: nil, repeat: true)
    

    在XQProxy中,打破了原有的self->timer->self的循环引用结构,新结构为self->XQProxy->timer->XQProxy--/weak/--self。XQProxy会在执行xq_timerFire时,检测是否还存在相应的target,如果不存在,就停止time,并且置为nil,打破time与proxy的互相持有关系。

    总结: 引入XQProxy作为中介者,XQProxy使用weak持有target,不影响target的正常释放。XQProxy持有timer和调用者,就可以控制调用流程,这样就达到了中介者在中间调控的目的

    RxSwift的deallocating分析

    下面我们看下RxSwift的deallocating的调用流程

    1. 外部调用代码
    _ = rx.deallocating
        .subscribe(onNext:{() in
            print("即将要释放")
        })
    
    1. deallocating的实现如下,创建了一个proxy,并且调用proxy.messageSent返回一个序列,那么我们先分析self.registerMessageInterceptor(deallocSelector)执行了什么操作,

    注意:定义deallocSelector的原因是在ARC下无法直接写#selector(dealloc),不允许重写dealloc,所以需要以string形式生成方法

    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)
                }
            }
        }
    
    1. registerMessageInterceptor方法中,最重要的步骤是执行了RX_ensure_observing,其中隐藏了方法交换操作
    fileprivate func registerMessageInterceptor<T: MessageInterceptorSubject>(_ selector: Selector) throws -> T {
            var error: NSError?
            let targetImplementation = RX_ensure_observing(self.base, selector, &error)
            subject.targetImplementation = targetImplementation
            return subject
        }
    
    1. RX_ensure_observing的前面都是为了调用加锁,保证执行的安全性,这里之所以使用oc代码是因为要使用到runtime,直接查看[self ensurePrepared:target forObserving:selector error:error]的实现
    IMP __nullable RX_ensure_observing(id __nonnull target, SEL __nonnull selector, NSErrorParam error) {
        __block IMP targetImplementation = nil;
        @synchronized(target) {
            @synchronized([target class]) {
                [[RXObjCRuntime instance] performLocked:^(RXObjCRuntime * __nonnull self) {
                    targetImplementation = [self ensurePrepared:target
                                                   forObserving:selector
                                                          error:error];
                }];
            }
        }
    
        return targetImplementation;
    }
    
    1. ensurePrepared方法的核心实现如下,调用[self swizzleDeallocating:deallocSwizzingTarget error:error]
    -(IMP __nullable)ensurePrepared:(id __nonnull)target forObserving:(SEL __nonnull)selector error:(NSErrorParam)error {
        if (selector == deallocSelector) {
            if (![self swizzleDeallocating:deallocSwizzingTarget error:error]) {
                return nil;
            }
        }
    }
    
    1. 点击进入swizzleDeallocating会看到一个宏定义如下,此处使用宏定义的目的是为了在编译时刻就生成对应的方法,提高运行效率
    SWIZZLE_INFRASTRUCTURE_METHOD(
        void,
        swizzleDeallocating,
        ,
        deallocSelector,
        DEALLOCATING_BODY
    )
    
    1. 下面宏定义将method_name转化为-(BOOL)method_name:(Class __nonnull)class parameters,
    #define SWIZZLE_INFRASTRUCTURE_METHOD(return_value, method_name, parameters, method_selector, body, ...)               \
        SWIZZLE_METHOD(return_value, -(BOOL)method_name:(Class __nonnull)class parameters error:(NSErrorParam)error        \
            {                                                                                                              \
                SEL selector = method_selector; , body, NO_BODY, __VA_ARGS__)   
    
    1. SWIZZLE_METHOD的定义如下,为了更方便查看,去除了定义中的\。其实质是生成两个函数newImplementationGenerator与replacementImplementationGenerator,并且调用[self ensureSwizzledSelector:selector ofClass:class newImplementationGenerator:newImplementationGenerator replacementImplementationGenerator:replacementImplementationGenerator error:error];
    #define SWIZZLE_METHOD(return_value, method_prototype, body, invoked_body, ...)                                           
    method_prototype                                                          
        __unused SEL rxSelector = RX_selector(selector);                      
        IMP (^newImplementationGenerator)(void) = ^() {                       
            __block IMP thisIMP = nil;                                     
            id newImplementation = ^return_value(__unsafe_unretained id self DECLARE_ARGUMENTS(__VA_ARGS__)) {                
                body(__VA_ARGS__)  
                struct objc_super superInfo = {                               
                    .receiver = self,                                 
                    .super_class = class_getSuperclass(class)
                };           
                return_value (*msgSend)(struct objc_super *, SEL DECLARE_ARGUMENTS(__VA_ARGS__))                              
                    = (__typeof__(msgSend))objc_msgSendSuper;                                                                 
                @try {             
                  return msgSend(&superInfo, selector ARGUMENTS(__VA_ARGS__));
                }                             
                @finally { invoked_body(__VA_ARGS__) }                  
            };  
            thisIMP = imp_implementationWithBlock(newImplementation);         
            return thisIMP;                                
        };                                                                               
        IMP (^replacementImplementationGenerator)(IMP) = ^(IMP originalImplementation) {                                      
            __block return_value (*originalImplementationTyped)(__unsafe_unretained id, SEL DECLARE_ARGUMENTS(__VA_ARGS__) )  
                = (__typeof__(originalImplementationTyped))(originalImplementation);           
            __block IMP thisIMP = nil;                                                                                        
            id implementationReplacement = ^return_value(__unsafe_unretained id self DECLARE_ARGUMENTS(__VA_ARGS__) ) {       
                body(__VA_ARGS__)                                                                                             
                @try {                                                                                                        
                    return originalImplementationTyped(self, selector ARGUMENTS(__VA_ARGS__));                                
                }                                                                                                             
                @finally { invoked_body(__VA_ARGS__) }                                                                        
            };           
            thisIMP = imp_implementationWithBlock(implementationReplacement);                            
            return thisIMP;                                                                                                   
        };           
        return [self ensureSwizzledSelector:selector          
                                    ofClass:class
                 newImplementationGenerator:newImplementationGenerator 
         replacementImplementationGenerator:replacementImplementationGenerator
                                      error:error]; 
     }                                                                      
    
    1. 在新生成的方法中调用了body(VA_ARGS),这个参数为DEALLOCATING_BODY宏定义,即调用[observer deallocating];
    #define DEALLOCATING_BODY(...)                                                        \
        id<RXDeallocatingObserver> observer = objc_getAssociatedObject(self, rxSelector); \
        if (observer != nil && observer.targetImplementation == thisIMP) {                \
            [observer deallocating];                                                      \
        }
    
    1. ensureSwizzledSelector方法中,class_addMethod(class, selector, newImplementation, encoding)是为类的添加新的方法实现,其中,class为当前类,selector为deallocSelector,newImplementation是定义的新的实现,由第9步知道新的实现先调用了[observer deallocating]
    -(BOOL)ensureSwizzledSelector:(SEL __nonnull)selector
                          ofClass:(Class __nonnull)class
       newImplementationGenerator:(IMP(^)(void))newImplementationGenerator
    replacementImplementationGenerator:(IMP (^)(IMP originalImplementation))replacementImplementationGenerator
                            error:(NSErrorParam)error {
        IMP newImplementation = newImplementationGenerator();
        if (class_addMethod(class, selector, newImplementation, encoding)) {
            // new method added, job done
            [self registerInterceptedSelector:selector implementation:newImplementation forClass:class];
            return YES;
        }
        return YES;
    }
    
    1. 第2步中,proxy对象遵循的协议DeallocatingProxy定义deallocating调用self.messageSent.on(.next(())),messageSent即为ReplaySubject对象,根据RxSwift核心流程,调用on(.next)等同于调用外部订阅的onNext方法
        fileprivate final class DeallocatingProxy : MessageInterceptorSubject, RXDeallocatingObserver {
            typealias Element = ()
            let messageSent = ReplaySubject<()>.create(bufferSize: 1)
            @objc func deallocating() {
                self.messageSent.on(.next(()))
            }
        }
    

    总结,RxSwift使用DeallocatingProxy类,创建出ReplaySubject,交换更新原有类的dealloc方法,在调用时先触发外部订阅的ReplaySubject.onNext,然后再释放对象,达到了由DeallocatingProxy控制释放流程通知外部的机制。

    相关文章

      网友评论

          本文标题:RxSwift-中介者模式&deallocating

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