RxSwift-中介者模式&deallocating

2019-08-12  本文已影响0人  小强_123

我们先由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控制释放流程通知外部的机制。

上一篇下一篇

猜你喜欢

热点阅读