我正在继承NSURLConnection,并使用MGTwitterEngine作为基础来帮助我开始。这可能是无关紧要的。但是,我注意到他们的代码中没有使用@property
或@synthesize
作为他们的ivars。他们将ivars包裹在访问器方法中,如下所示:
- (NSString *)identifier {
return [[_identifier retain] autorelease];
}
我的问题是两部分。首先,retain
后跟autorelease
有什么影响?在我看来它会取消本身,或者更糟糕的是泄漏。
其次,如果我要更改头文件:
@property (nonatomic, retain, readonly) NSString* _identifier;
并使用@synthesize indentifier = _identifier
,这不会与访问者方法做同样的事情而不必写它吗?
也许这只是两种不同的方式来做同样的事情。但我想确保我有正确的理解。感谢。
答案 0 :(得分:8)
使用@synthesize
实际上只会创建一个setter和一个getter方法。为您自动生成的代码保证使用适当的内存管理,因此您无需担心。
MGTwitterEngines使用return [[ivar retain] autorelease
]实际上是正确的方法。让我们举两个例子。
假设getter定义如下:
-(Foo)foo {
return foo;
}
然后我们执行此代码:
bar = [[bar alloc] init];
// bar的计数为1。foo = bar.foo;
// foo保留计数为1(由酒吧拥有)。[bar release];
//酒吧及其所有的ivars都是imidiatetly释放![foo doSomething];
//自上一行释放foo以来,这将崩溃。如果我们改为将getter更改为:
-(Foo)foo {
return [[foo retain] autorelease];
}
bar = [[bar alloc] init];
//栏的保留计数为1 foo = bar.foo;
// foo的保留计数为2(一个由bar拥有,一个由autorelease pool拥有)。[bar release];
//酒吧及其所有的ivars都是imidiatetly释放![foo doSomething];
//因为foo仍然存在并且由autorelease池拥有,所以不会崩溃。希望这能解释为什么你应该总是从你所有的getter中正确地返回自动释放的对象。重要的是,任何返回值都可以在其父级的解除分配中继续存在,因为没有类可以保证客户端在暴露给野外时对其值的影响。
答案 1 :(得分:3)
保留然后自动释放完全符合您的想法。它向对象发送retain
消息,然后向其发送autorelease
消息。请记住,自动释放对象会将该对象添加到自动释放池但不会将其释放。自动释放池将在运行循环的当前迭代结束时向对象发送release
消息。因此,retain
后跟autorelease
基本上说,“确保此对象保持不变,直到运行循环的当前迭代结束。”如果您需要将返回值挂起更长时间,则可以保留它。如果没有,不做任何事情,自动释放池将处理它。
在这种情况下,发送retain
和autorelease
消息的字符串是属性。它已由父对象保留。所以你可能想知道为什么这个保留和自动释放的东西呢?好吧,不能保证在运行循环的当前迭代结束之前对象不会释放_identifier
。考虑这个例子:
- (NSString *)identifier { return _identifier; }
- (void)aMethod {
NSString *localId = [self identifier]; // localId refers to _identifier which is only retained by self
[self methodThatChangesIdentifierAndReleasesItsOldValue]; // self releases _identifier
NSLog(@"%@", localId); // crash, because localId (old value of _identifier) has been released
}
在这种情况下,返回的标识符不会保留并自动释放。 NSLog
行崩溃,因为localId
引用了已发布的字符串。但是,如果我们在getter中使用retain
和autorelease
,则不会发生崩溃,因为在运行循环的当前迭代结束之前不会释放localId
。
据我所知,您使用identifier
财产取代会同样出色。它可能不是相同的代码,但效果应该是相同的。
答案 2 :(得分:1)
Apple在Implementing Accessor Methods中解释得很清楚。您引用的方法(Apple称为“技术1”)有助于避免错误,如果调用者为标识符属性分配新值,然后期望检索到的值仍然可用。大部分时间都不需要它,但只返回ivar值就可能导致难以追踪的错误。
答案 3 :(得分:0)
一般来说,如果你要归还一些你不是第一名的东西,那么就会保留自动释放。如果您拥有_identifier
并且保留/ alloc / etc与发送到该对象的release / autorelease不匹配,它将只会泄漏。
其次,是的,如果你没有做超出一般样板文件的特殊事情,你通常不必编写标题。 Apple有关于属性的良好文档,我建议如果你仍然模糊,你看看那些。