给出以下属性定义:
@property (nonatomic,retain) MyObject* foo;
以下代码会导致内存泄漏:
self.foo = [[MyObject alloc] init];
看起来alloc调用会将对象的保留计数增加到1,然后属性setter中的retain会将其增加到1.但由于初始计数从未递减为0,所以即使在self时对象也会保持不变被释放。这种分析是否正确?
如果是这样,看起来我有两种选择:
self.foo = [[[MyObject alloc] init] autorelease];
出于性能原因不建议在iPhone上使用,或者:
MyObject* x = [[MyObject alloc] init];
self.foo = x
[x release];
这有点麻烦。还有其他选择吗?
答案 0 :(得分:3)
还有其他选择吗?
没有
如果不使用自动释放,你将无法编写大量的iPhone应用程序,Cocoa Touch库会在很多地方使用它们。理解它正在做什么(将指针添加到下一帧的删除列表中)并避免在紧密循环中使用它。
你可以在MyObject上使用class方法来执行alloc / init / autorelease来清理它。
+ (MyObject *)object {
return [[[MyObject alloc] init] autorelease];
}
self.foo = [MyObject object];
答案 1 :(得分:3)
在iPhone上管理保留属性的最简单方法如下(自动释放并不像您想象的那么糟糕,至少对于大多数用途而言):
-(id)init {
if (self = [super init]) {
self.someObject = [[[Object alloc] init] autorelease];
}
return self;
}
-(void)dealloc {
[someObject release];
[super dealloc];
}
autorelease
释放对分配给self.object
的浮动实例的引用,该实例保留了自己的引用,为您提供了所需的引用(someObject
)。然后,当类被销毁时,唯一剩下的引用被释放,从而破坏对象。
如另一个答案所述,您还可以创建一个或多个“构造函数”消息,以使用可选参数创建和自动释放对象。
+(Object)object;
+(Object)objectWithCount:(int)count;
+(Object)objectFromFile:(NSString *)path;
可以将这些定义为:
// No need to release o if fails because its already autoreleased
+(Object)objectFromFile:(NSString *)path {
Object *o = [[[Object alloc] init] autorelease];
if (![o loadFromFile:path]) {
return nil;
}
return o;
}
答案 2 :(得分:2)
你是对的,self.foo = [[MyObject alloc] init];
正在泄漏记忆。两种选择都是正确的,可以使用。关于这样一个语句中的autorelease
:请记住,一旦当前运行循环结束,对象将由自动释放池释放,但它很可能会被self
保留更长时间,所以这里的内存使用率没有问题。