在swift
中存在一个析构函数deinit
,在RXSwift
中也有类似的函数deallocating
和deallocated
,那么他们之间有什么联系吗?
我们通过一个小demo
打印一下:
demo
override func viewDidLoad() {
super.viewDidLoad()
_ = rx.deallocating.subscribe(onNext: { () in
print("准备走了-deallocating")
})
_ = rx.deallocated.subscribe(onNext: { () in
print("已经走了-deallocated")
})
}
deinit {
print("走了-deinit")
}
输出:
准备走了-deallocating
走了-deinit
已经走了-deallocated
我们可以看见在系统的析构函数
deinit
前后会调用deallocating
和deallocated
,这是为什么呢,让我们通过源码来看一下。
deallocating
第一步,deallocating
序列的创建
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)
}
}
}
首先通过反射机制拿到系统的析构函数dealloc
,然后调用registerMessageInterceptor
初始化一个类型为DeallocatingProxy
的proxy
。
fileprivate func registerMessageInterceptor<T: MessageInterceptorSubject>(_ selector: Selector) throws -> T {
let rxSelector = RX_selector(selector)
let selectorReference = RX_reference_from_selector(rxSelector)
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;
@synchronized(target) {
@synchronized([target class]) {
[[RXObjCRuntime instance] performLocked:^(RXObjCRuntime * __nonnull self) {
targetImplementation = [self ensurePrepared:target
forObserving:selector
error:error];
}];
}
}
return targetImplementation;
}
首先加了锁,然后看到了返回的targetImplementation
调用ensurePrepared
方法,点击进去看看
-(IMP __nullable)ensurePrepared:(id __nonnull)target forObserving:(SEL __nonnull)selector error:(NSErrorParam)error {
Method instanceMethod = class_getInstanceMethod([target class], selector);
if (selector == deallocSelector) {
Class __nonnull deallocSwizzingTarget = [target class];
IMP interceptorIMPForSelector = [self interceptorImplementationForSelector:selector forClass:deallocSwizzingTarget];
if (interceptorIMPForSelector != nil) {
return interceptorIMPForSelector;
}
if (![self swizzleDeallocating:deallocSwizzingTarget error:error]) {
return nil;
}
interceptorIMPForSelector = [self interceptorImplementationForSelector:selector forClass:deallocSwizzingTarget];
if (interceptorIMPForSelector != nil) {
return interceptorIMPForSelector;
}
}
}
这段代码中包含了一句很重要的信息[self swizzleDeallocating:deallocSwizzingTarget error:error]
由名字就可以看出黑魔法进行了方法交换。
SWIZZLE_INFRASTRUCTURE_METHOD(
void,
swizzleDeallocating,
,
deallocSelector,
DEALLOCATING_BODY
)
点进来,代码很少啊,一个宏和几个参数,那我们来看看这个宏做了什么? 我们将这段宏还原成下面的代码,方便阅读
-(BOOL)swizzleDeallocating:(Class __nonnull)class error:(NSError *)error{
SEL selector = NSSelectorFromString(@"delloc");
__unused SEL rxSelector = NSSelectorFromString(@"_RX_namespace_delloc");
IMP (^newImplementationGenerator)(void) = ^() {
__block IMP thisIMP = nil;
id newImplementation = ^void(__unsafe_unretained id self DECLARE_ARGUMENTS(__VA_ARGS__)) {
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 { invoked_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__) ) {
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];
}
接下来会来到return
的ensureSwizzledSelector
方法,
-(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);
ALWAYS(originalImplementation != nil, @"Method must exist.");
IMP implementationReplacementIMP = replacementImplementationGenerator(originalImplementation);
ALWAYS(implementationReplacementIMP != nil, @"Method must exist.");
IMP originalImplementationAfterChange = method_setImplementation(existingMethodOnTargetClass, implementationReplacementIMP);
ALWAYS(originalImplementation != nil, @"Method must exist.");
return YES;
}
通过
method_setImplementation
将dealloc
的IMP
指向代码块replacementImplementationGenerator
中。所以当系统触发了dealloc
函数,就会来到块replacementImplementationGenerator
中
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__) ) {
body(__VA_ARGS__)
@try {
return originalImplementationTyped(self, selector ARGUMENTS(__VA_ARGS__));
}
@finally { invoked_body(__VA_ARGS__) }
};
thisIMP = imp_implementationWithBlock(implementationReplacement);
return thisIMP;
};
当完成一系列操作以后会来到{ invoked_body(__VA_ARGS__) }
,进来的时候传了4个参数,让我们看最后一个参数DEALLOCATING_BODY
#define DEALLOCATING_BODY(...) \
id<RXDeallocatingObserver> observer = objc_getAssociatedObject(self, rxSelector); \
if (observer != nil && observer.targetImplementation == thisIMP) { \
[observer deallocating]; \
}
我们看见他拿到了替换后的方法deallocating
,当系统调用delloc
的时候就会调用deallocating
@objc func deallocating() {
self.messageSent.on(.next(()))
}
deinit {
self.messageSent.on(.completed)
}
DeallocatingProxy
中保存ReplaySubject
序列,并在deallocating()
进行发送响应。
这就是为什么deallocating
会在deinit
前面响应了。
deallocated
在来看一下deallocated
public var deallocated: Observable<Void> {
return self.synchronized {
if let deallocObservable = objc_getAssociatedObject(self.base, &deallocatedSubjectContext) as? DeallocObservable {
return deallocObservable._subject
}
let deallocObservable = DeallocObservable()
objc_setAssociatedObject(self.base, &deallocatedSubjectContext, deallocObservable, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return deallocObservable._subject
}
}
fileprivate final class DeallocObservable {
let _subject = ReplaySubject<Void>.create(bufferSize:1)
init() {
}
deinit {
self._subject.on(.next(()))
self._subject.on(.completed)
}
}
内部初始化了
ReplaySubject
,当调用系统函数deinit
后,就会发送响应。
总结:
在RxSwift
中提供了两个和deinit
有关的序列,观察dealloc
的调用,其中deallocating
内部替换了原生的dealloc
方法从而达到监听dealloc
的调用
这里并不是交换方法,而是在replacementImplementationGenerator
代码块中先保留了dealloc
的函数地址,再通过imp_implementationWithBlock
设置dealloc
的IMP,指向了replacementImplementationGenerator
代码块
调用dealloc
方法就会调用了代码块,在代码块内部通过body
函数调用了deallocating
方法,之后执行代码块中保留的原dealloc
函数。