以下两种分配和初始化对象的方法有什么区别?
AController *tempAController = [[AController alloc] init]; self.aController = tempAController; [tempAController release];
和
self.aController= [[AController alloc] init];
大多数苹果示例使用第一种方法.为什么要分配,初始化和对象然后立即释放?
每个对象都有一个引用计数.当它变为0时,对象被释放.
假设该属性被声明为@property (retain)
:
你的第一个例子,逐行:
该对象是由创建的alloc
,它的引用计数为1.
该对象被移交给self
的setAController:
方法,该方法将它发送一个retain
消息(因为该方法不知道该对象是来自),递增其引用计数为2.
调用代码不再需要对象本身,因此它调用release
,将引用计数递减为1.
您的第二个示例基本上执行步骤1和2但不执行步骤3,因此最后对象的引用计数为2.
规则是,如果您创建了一个对象,那么当您完成它时,您有责任释放它.在您的示例中,代码在设置属性后使用tempAController完成.retain
如果需要该对象的话,setter方法的责任就是调用它.
重要的是要记住,self.property = foo;
Objective-C实际上只是简写,[self setProperty:foo];
并且该setProperty:
方法将根据需要保留或复制对象.
如果声明了属性@property (copy)
,则该对象将被复制而不是保留.在第一个例子中,原始对象将立即释放; 在第二个示例中,原始对象的引用计数将为1,即使它应该为0.因此您仍然希望以相同的方式编写代码.
如果声明了属性@property (assign)
,那么self
就不会声明对象的所有权,而其他人则需要保留它.在这种情况下,第一个例子是不正确的.这些属性很少见,通常仅用于对象委托.
正如其他人所说,你展示的两个代码片段并不相同(出于内存管理的原因).至于为何选择前者而不是后者:
后者的正确表述将是
self.aController= [[[AController alloc] init] autorelease];
与前者相比,这通过使用自动释放池增加了额外的开销,并且在某些情况下将导致对象的生命周期被不必要地扩展(直到自动释放池被释放),这将增加应用程序的内存占用.
另一个"可能的"实现(取决于示例的来源)简单地说:
aController = [[AController alloc] init];
但是,强烈建议不要在init或dealloc方法之外的任何地方直接设置实例变量.在其他地方,您应该始终使用访问器方法.
这将我们带到示例代码中显示的实现:
AController *tempAController = [[AController alloc] init]; self.aController = tempAController; [tempAController release];
这符合以下最佳做法:
它避免了自动释放;
它使内存管理语义立即清晰;
它使用访问器方法来设置实例变量.
另请注意,您希望将代码缩减到一行是许多人使用Autorelease的原因:
self.aController = [[[AController alloc] init] autorelease];
虽然从理论上讲,iPhone自动释放在某种程度上更加昂贵(从未听说过明确的解释原因),因此您可能希望在将对象分配到其他位置后立即显式释放.
如果您正在使用Xcode,它可以帮助您使用静态分析器检测此类代码.点击Build >> Build and Analyze
这将在这些代码片段中向您显示一条非常有用的消息.