【问题标题】:Swizzling methods, that implicitly return a retained object under ARCSwizzling 方法,隐式返回 ARC 下的保留对象
【发布时间】:2016-02-18 23:54:05
【问题描述】:

例如,让我们考虑 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

在这段代码中,原来的copyWithZone:方法是隐式返回一个保留对象,因为它属于copy方法族。但我的myCopyWithZone: 不是。

我预计会崩溃,但看起来这段代码工作正常。当然,我可以重命名我的方法以避免混淆。但我很好奇幕后到底发生了什么?

【问题讨论】:

    标签: objective-c automatic-ref-counting method-swizzling


    【解决方案1】:

    如您所知,ARC 检查方法名称,应用 Cocoa 内存管理命名约定,并确定方法的行为方式。对于它正在编译的方法,它使该方法遵守这些约定。对于它正在调用的方法,它假定该方法遵循这些约定。

    (可以使用函数属性覆盖约定,但暂时忽略它。)

    当 ARC 编译您的 -myCopyWithZone: 时,它确定此类方法应返回 +0 引用。当遇到对(显然)-myCopyWithZone: 的调用时,它假定该方法返回 +0 引用。由于这些匹配,它不应该保留或释放任何东西。 (好吧,它可能会暂时保留结果,但它必须通过自动释放来平衡。)结果,原始-copyWithZone: 返回的实际 +1 引用保留给调用者和调用者期待 +1 推荐,所以这一切都很好。

    您可能会通过调用返回 +1 引用的不同方法(不会通过 swizzling 有效地重命名)来导致 ARC 搞砸。如果要返回它,并且由于当前方法预计返回 +0 引用,它将自动释放它。调用者不会保留它,因为它期望 +1 引用。所以对象会被提前释放,很可能会导致崩溃。

    【讨论】:

      猜你喜欢
      • 2014-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-27
      • 1970-01-01
      • 1970-01-01
      • 2012-05-05
      • 1970-01-01
      相关资源
      最近更新 更多