为什么在使用setter将自定义对象分配给实例变量时使用自动释放?

时间:2013-04-16 22:05:43

标签: objective-c macos memory-management

我想将自定义对象分配给实例变量。

这是代码:
- MyController.h / .m

#import "CustomData.h"  
@interface MyViewController : NSViewController  
@property (retain) CustomData* theData;  

- (void)aRandomMethod; 

@end

@implementation MyViewController  
@synthetize theData;  

- (void)aRandomMethod {  

   NSData* rawData = [someOtherObject someOtherMethod];

   // option 1
   self.theData = [[CustomData alloc] initWithData:rawData];

   // option 2
   CustomData* _theData = [[Custom alloc] initWithData:rawData];

   // option 3
   self.theData = [[[CustomData alloc] initWithData:rawData] autorelease];

   // option 4
   theData = [[CustomData alloc] initWithData:rawData];

   // ... later code calls some methods on theData or _theData, not useful here.
 }
@end

在Xcode中运行Analyze功能时,它告诉我,对于选项1和2,有一个“泄漏的对象未被引用...”,但对于3和4则没有。似乎我需要{{1使用setter时的自定义对象。我知道在返回方法中我们拥有的对象时需要使用autorelease

你能为每个选项解释为什么它是错的还是对的?感谢。

2 个答案:

答案 0 :(得分:5)

选项1是错误的,因为你alloc是该方法中的对象,因此该方法现在拥有该对象,因此需要release它。当您将其分配给某个媒体资源时,retain会将其release分配给alloc。当它完成时,它就会release

出于同样的原因,选项2是错误的。你取出它的属性部分,但因为你用autorelease创建了对象,你负责用该方法调用release

选项3是正确的,因为在将它提供给属性之前你已release,因此该方法不再拥有它。请注意,如果您在此处使用了retain,那么它会中断,因为它会在release财产获得{{1}}之前{{1}}。

选项4可能是正确的;我假设它正在将它分配给ivar。如果您稍后在dealloc方法中手动释放ivar,那么这是正确的。通过房产通常会更好。否则,您将面临分配其他值并忘记{{1}}现有值的风险。

答案 1 :(得分:1)

选项1和2最值得注意的是存在一个alloc,因此需要相应的版本。

选项1本质上是“隐藏的”,因为编译器会自动为您生成setter和getter。您没有看到的是,当使用点表示法时,您将通过setter,它隐含地包含一个保留调用。因此,您将分配对象AND retain,使其保留计数为2.

因此,为了确保将来能够正确发布,您必须将其指定为添加到自动释放池中,以便系统稍后进行清理。这将使保留计数为1,然后在您的dealloc方法中,您可以安全地释放该属性。