在getter方法中保留和自动释放

Mal*_*loc 4 getter release objective-c autorelease

我正在学习内存管理,但我真的不明白为什么我应该像这样实现我的属性getter:

-(Weapon*)myWeapon
{
    [myWeapon retain];
    [myWeapon autorelease];
    return myWeapon;
}
Run Code Online (Sandbox Code Playgroud)

我理解我的写作,但我无法想象它为什么重要?你能解释一下我为什么要这样做吗?

Ric*_*ich 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.
    }
}
Run Code Online (Sandbox Code Playgroud)

因为从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.
}
Run Code Online (Sandbox Code Playgroud)

在比使用setter更频繁地调用getter的情况下,技术2的性能明显优于技术1.

技术3技术3完全避免使用自动释放:

- (NSString*) title {
    return title;
}

- (void) setTitle: (NSString*) newTitle {
    if (newTitle != title) {
        [title release];
        title = [newTitle retain]; // Or copy, depending on your needs.
    }
}
Run Code Online (Sandbox Code Playgroud)

技术3使用的方法适用于经常调用的getter和setter方法.它也适用于不希望延长其值的生命周期的对象,例如集合类.它的缺点是可能会立即释放旧值(如果没有其他所有者),如果另一个对象维护对它的非拥有引用,则会导致问题.例如:

NSString *oldTitle = [anObject title];
[anObject setTitle:@"New Title"];
NSLog(@"Old title was: %@", oldTitle);
Run Code Online (Sandbox Code Playgroud)

如果anObject是唯一拥有原始标题字符串的对象,则在设置新标题后将取消分配该字符串.然后log语句会导致崩溃,因为oldTitle是一个释放的对象.

编辑:基本上保留然后自动释放的目的是确保如果在调用范围有机会保留它之前更改属性值,则不会释放对象.除非你有异步代码,否则这通常不是问题.在大多数情况下- (Weapon *)myWeapon { return myWeapon; }都很好(加上它更快).