指定的局部变量对实例变量的ARC行为

时间:2016-04-19 02:45:56

标签: objective-c automatic-ref-counting

问题1

假设我有这段代码:

MyClass * __strong foo = [MyClass new];
MyClass * __strong bar = foo;
// foo = nil; // by ARC?

this answer的引用中,ARCfoo获取了引用后,{3}}是否自动将bar排除在外{1}}

问题2

//ECGService.m
@property (strong) MuttableArray *rriData;

(MuttableArray *)getRriData {
    return _rriData;
}

//AlgorithmTest.m
// according to Apple docs, local variable are marked __strong by default
MuttableArray *rriData = [self.ecgService getRriData];
for(NSNumber *rri in rriData) {
    // use rri!
}
// rriData = nil;

使用后我应该将局部变量rriData弄清楚吗?

而且,__strong属性是否只能应用于对象的一个​​实例?

3 个答案:

答案 0 :(得分:1)

  

参考这个答案,由于bar已经获得了参考资料,ARC是否会在第3行自动淘汰foo?

没有。 ARC代表自动参考计数。显然,计数并不止于1。

ARC的优势在于每个引用都独立于其他引用进行处理。强大的foo只要指向就保留引用的对象。无关紧要,其他引用变量是否指向同一个对象。跟踪隔离的每个参考。

只有一种情况让ARC更改引用变量的值:如果它用weak标记,并且没有对该对象的其他强引用。这是预期的行为。

作为优化的结果,可以省略保留和释放,或者将源代码中的不同局部变量放在一起。这对你来说很透明。

  

使用后我应该将局部变量rriData弄清楚吗?

你不应该关心这个。强引用变量自动保留一个对象,其引用存储在引用变量中。并且它会自动释放对象,如果它不再指向它。这包括

上的发布
  • 为参考变量
  • 分配新值
  • nil已分配给参考变量
  • 引用变量丢失了它(生命周期)。

由于最后一个事实,当rriData失去它时,会有一个自动生成的版本。没有理由提前把它弄清楚。

答案 1 :(得分:1)

答案1。

原则上,ARC不会“忽略”foo,直到它超出范围。当它超出范围时,ARC会发布其引用。它不必将foo实际设置为nil,但效果就像ARC将其设置为nil一样。

在实践中,ARC通常允许在最后一次使用foo变量之后立即释放foo所持有的引用,这可能在它超出范围之前很久。在您的示例中,如果您在函数中使用foo的唯一位置是bar的赋值,则允许ARC在该赋值后立即释放foo的引用。请注意,通常您无法了解此早期版本,因为您不再使用foo!另请注意,bar仍会引用该对象,除非bar稍后也未在函数中使用。

有一些特殊属性可以阻止ARC执行此早期版本,称为objc_precise_lifetimeobjc_returns_inner_pointer,但通常通过宏NS_VALID_UNTIL_END_OF_SCOPENS_RETURNS_INNER_POINTER应用。这些是您可能不会很快担心的高级功能,但如果您想查看NS_RETURNS_INNER_POINTER的一些示例,请查看NSString.h

答案2。

您不需要“忽略”rriData。当ARC超出范围时(或更快看到答案1),ARC将发布其参考。

您通常不需要说__strong,因为它是默认设置,而且通常是您想要的。对对象进行多次强引用是正常的。当您需要阻止保留周期时,可以显式使用__weak。关于网络上的保留周期和堆栈溢出有很多解释,所以如果你需要了解它们,请访问你最喜欢的搜索引擎。

答案 2 :(得分:0)

问题1.不,您最终会得到两个对MyClass实例的引用。什么都没有了。

问题2.不,你不需要做任何事情。 ARC为您管理记忆。这就是重点。你也永远不需要说__strong。这是默认值。