启用 ARC 后,将不会在此代码中放入自动释放池
sn-p?
答案是,可以,也可以不。 ARC 不做任何保证。这里方法的名称(obj)不以表示保留返回类型的特殊名称之一(例如alloc、retain、new、copy、mutableCopy)开头,所以它返回非保留参考。 ARC specification section on "Unretained return values" 说:
在最坏的情况下,这可能涉及自动释放,但调用者必须
不要假设该值实际上在自动释放池中。
在过去,在 MRC 下,您必须在这种情况下执行 autorelease 它才能返回,因为该方法需要返回非保留引用,但必须有人持有对该对象的强引用或否则它将被释放。由于对象是在您的方法中创建的,因此没有其他人对它有引用,并且该方法必须在其作用域结束时摆脱其强引用,因为它不能返回保留引用,所以唯一的方法是让自动释放池在整个回报中具有很强的参考价值。
ARC 必须与 MRC 保持 ABI 兼容(即,您应该能够用 ARC 替换 MRC 实现,反之亦然,而无需更改标头,并且调用者不需要知道它是使用 ARC 编译还是使用 MRC 编译即可工作正确)。因此,在从 MRC 代码调用你的方法的情况下,遵循与上一段相同的逻辑,你的方法必须autorelease;根本没有其他办法。
但是,ARC 引入了一种巧妙的可选运行时优化,在某些情况下,当调用者和被调用者都使用 ARC 编译时,它可以消除 autorelease,而调用者或被调用者不需要了解另一方。这大概是它的工作原理:在函数的返回中,通常是autorelease,ARC 改为调用objc_autoreleaseReturnValue()。在调用函数并保留返回值的代码中,它改为调用objc_retainAutoreleasedReturnValue()。在objc_autoreleaseReturnValue() 中,它在堆栈帧上方查看返回地址,以查看返回值是否将传递给objc_retainAutoreleasedReturnValue()。如果没有,它将autorelease。如果是,那么它将跳过autorelease,并修改返回地址以跳过objc_retainAutoreleasedReturnValue,从而删除autorelease 和retain,从而取消。在objc_retainAutoreleasedReturnValue() 中,如果没有被跳过,它将只是retain。这适用于 MRC 到 ARC 调用、ARC 到 ARC 调用和 ARC 到 MRC 调用,并且将消除某些 ARC 到 ARC 调用的autorelease。
还有,这两个代码sn-ps有什么区别?
第一个会将其放入自动释放池中,而第二个可能不会。 (顺便说一下__strong是默认的,所以第三段代码和第一段是一样的)
但本质上没有充分的理由使用__autoreleasing 作为局部变量而不是默认值(即__strong); __strong 更简单,更容易思考。
通常你会遇到__autoreleasing的唯一一次是在参数中的“指向”类型——如果一个函数声明它需要一个指向__autoreleasing的指针(例如NSObject * __autoreleasing *),这意味着它会写以不同于指向__strong(例如NSObject * __strong *)的指针的方式指向指向的变量。两种方式都可以,但是调用者和被调用者需要就哪一种达成一致。由于在 Cocoa 中普遍使用NSError * __autoreleasing *,所以一个不合格的默认指向__autoreleasing 的指针(例如NSObject ** 表示NSObject * __autoreleasing *)。