Bor*_*kyi 5 objective-c automatic-ref-counting method-swizzling
例如,让我们考虑ARC下面的代码:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@implementation NSDate (MyEvilHack)
+ (void)load {
Method originalMethod = class_getInstanceMethod(self, @selector(copyWithZone:));
Method newMethod = class_getInstanceMethod(self, @selector(myCopyWithZone:));
method_exchangeImplementations(originalMethod, newMethod);
}
- (id)myCopyWithZone:(NSZone *)zone {
id result = [self myCopyWithZone:zone];
// do customization
return result;
}
@end
Run Code Online (Sandbox Code Playgroud)
在此代码中,原始copyWithZone:方法隐式返回一个保留对象,因为它属于copy方法族.但我myCopyWithZone:的不是.
我希望崩溃,但看起来这个代码正常工作.当然,我可以重命名我的方法以避免混淆.但我很好奇在引擎盖下究竟发生了什么?
如您所知,ARC 检查方法名称,应用 Cocoa 内存管理命名约定,并确定方法的行为方式。对于正在编译的方法,它使该方法遵守这些约定。对于它调用的方法,它假定该方法遵守这些约定。
(可以使用函数属性覆盖约定,但现在忽略它。)
当 ARC 编译您的 时-myCopyWithZone:,它确定此类方法应返回 +0 引用。当它遇到对(显然)的调用时-myCopyWithZone:,它假设该方法返回 +0 引用。由于这些匹配,它不应保留或释放任何内容。(嗯,它可能会暂时保留结果,但它必须通过自动释放来平衡结果。)因此,原始返回的实际-copyWithZone:+1 引用保留给调用者,并且调用者期望 +1 引用,所以这就是全部好的。
您可能会通过调用返回 +1 引用的不同方法(不会通过调整有效地重命名)来导致 ARC 搞砸。如果要返回该引用,并且由于当前方法预计返回 +0 引用,因此它将自动释放它。调用者不会保留它,因为它期望 +1 引用。因此该对象将被过早释放,可能导致崩溃。
| 归档时间: |
|
| 查看次数: |
85 次 |
| 最近记录: |