当指针设置为nil时,ARC不会释放(使用工厂方法)

时间:2013-02-03 14:28:35

标签: objective-c cocoa automatic-ref-counting

编辑:以下定义的问题实际上出现在此代码中:

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        XYZPerson *myPerson = [XYZPerson person];
        myPerson = nil;
        NSLog(@"The end.");
    }
}

方法'人'是工厂方法。


我有以下代码:

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        XYZPerson *myPerson = [[XYZPerson alloc] init];
        myPerson = nil;
        NSLog(@"The end.");
    }
}

XYZPerson会覆盖dealloc方法,以便使用NSLog打印出某些内容。我希望上面的代码能够输出如下内容:

Dealloc!
The end.

但它并不像我预期的那样:

The end.
Dealloc!

我做错了什么或是否误解了ARC的概念?

2 个答案:

答案 0 :(得分:4)

ARC保证在编译时自动引用对象。它更进一步,并要求代码在算法上完全一致(在尝试通过转换,例如void*id之间转换时表现为错误 - 在ARC下,您必须符合条件这些演员阵容中的内存管理策略。)

ARC不是垃圾收集器;没有扫描,没有线程,也没有停止世界的行为。这意味着以自动循环检测为代价的更可预测的行为。

虽然ARC保证会自动管理对象的生命周期,但ARC并不保证超出“对象的寿命至少与代码中使用的一样长,可能更长”。

实际上,您可能会看到生命周期更改,具体取决于代码的优化级别以及您调用的工厂方法是否在ARC与manual-retain-release [MRR]源文件中编译。并且生命周期可能会在编译器和/或运行时的版本中发生变化。

例如,调用工厂方法的ARC代码有时可能会使autorelease完全短路。

听起来很可怕,但这不是因为算法的一致性要求。由于不存在模棱两可的行为(正如旧的MRR中那样),生命周期可能会因版本而发生变化不应影响您的代码。

当然,这意味着您不应该dealloc方法之间存在顺序依赖关系。这不应该是一个繁重的要求,因为在MRR下dealloc方法之间的顺序依赖性总是令人讨厌的事情。

答案 1 :(得分:0)

这是因为ARC仍然遵守Cocoa内存管理命名约定。您可以像这样将属性添加到工厂方法person中:+ (instancetype)person __attribute__((objc_method_family(new)));,因此ARC假定它返回的对象带有增加的保留计数,该计数需要与相应的发行版进行平衡。然后在将变量设置为nil之后立即进行dealloc。