我正在学习内存管理,但我真的不明白为什么我应该像这样实现我的属性getter:
-(Weapon*)myWeapon
{
[myWeapon retain];
[myWeapon autorelease];
return myWeapon;
}
我理解我的写作,但我无法想象它为什么重要?你能解释我为什么要这样做吗?
答案 0 :(得分:10)
这来自内存管理编程指南:
技术1 在技术1中,getter返回的值在调用范围内自动释放:
- (NSString*) title {
return [[title retain] autorelease];
}
- (void) setTitle: (NSString*) newTitle {
if (title != newTitle) {
[title release];
title = [newTitle retain]; // Or copy, depending on your needs.
}
}
因为从get访问器返回的对象是在当前作用域中自动释放的,所以如果更改了属性值,它仍然有效。这使得访问器更加健壮,但代价是额外的开销。如果您希望频繁调用getter方法,则保留和自动释放对象的额外成本可能不值得花费性能。
技术2 与技术1一样,技术2也使用自动释放技术,但这次在setter方法中这样做:
- (NSString*) title {
return title;
}
- (void) setTitle: (NSString*) newTitle {
[title autorelease];
title = [newTitle retain]; // Or copy, depending on your needs.
}
技术2的性能明显优于技术1,在这种情况下,调用getter的频率远远高于setter。
技术3 技术3完全避免使用自动释放:
- (NSString*) title {
return title;
}
- (void) setTitle: (NSString*) newTitle {
if (newTitle != title) {
[title release];
title = [newTitle retain]; // Or copy, depending on your needs.
}
}
技术3使用的方法适用于经常调用的getter和setter方法。它也适用于不希望延长其值的生命周期的对象,例如集合类。它的缺点是可能会立即释放旧值(如果没有其他所有者),如果另一个对象维护对它的非拥有引用,则会导致问题。例如:
NSString *oldTitle = [anObject title];
[anObject setTitle:@"New Title"];
NSLog(@"Old title was: %@", oldTitle);
如果anObject是唯一拥有原始标题字符串的对象,则在设置新标题后将取消分配该字符串。因为oldTitle是一个释放的对象,因此log语句会导致崩溃。
编辑:基本上,保留然后自动释放的目的是确保在调用范围有机会保留属性值之前,如果更改属性值,则不会释放对象。除非你有异步代码,否则这通常不是问题。在大多数情况下- (Weapon *)myWeapon { return myWeapon; }
都很好(加上它更快)。
答案 1 :(得分:2)
正如ACBurk所说,但这里有一个很好的描述:
http://vgable.com/blog/2009/03/31/how-to-write-cocoa-object-getters/