我想帮助更好地理解Cocoa中字符串的内存特征。 我正在使用的应用程序使用一个视图控制器和n个工具对象。 View控制器在程序的生命周期中存在,但工具对象已分配并释放。
假设我有一个字符串toolName_,在我的实现中我配置了传入的工具对象:如果对象没有工具名称,我想将toolName_字符串设置为@“not set”。如果工具有名称,我想将字符串设置为工具的名称。
我想知道将传入值存储到toolName_的正确方法,因为有时这将是一个已分配的对象,有时这将是一个常量字符串。
-(BOOL)setToolObject: ToolObject: obj{
ToolObject someObj = nil;
someObj = [[ToolObject alloc]initWithObject obj];
if(someObj != nil){
if(! [someObj.toolName isEqualToString: @""]){
self->toolName_ = Which method should I use given the above question?
The last instance may have been a constant string but may not have.
[self->toolName_ release] (can I send a release message to a constant
string without causing a problem?)
self->toolName = [[NSString alloc]initWithString:someObj.toolName];
OR
self->tool name = [NSString stringWithString: someObj.toolName];
This method is self releasing but I don't own it and I'm still not sure
what happens to the constant string if it existed. I think I read it's
not recommended to use this on member vars.
}else{
self->toolName_ = @"not set";
}
return YES;
}else{
return NO;
}
}
建议表示赞赏。
答案 0 :(得分:1)
我强烈建议(可能)使用ARC,如果你不能使用它(或者你只是想了解内存管理是如何工作的?),不要从课外发送保留和释放消息。相反,你应该在访问器中执行此操作。
所以你应该创建一个retain或copy属性(通常使用不可变字符串比使用copy更好,因为它们可能被分配给可变字符串,所以假设你正在使用一个不可变的 - 因此是线程安全的 - 属性是无效的)。
所以在你的情况下,我建议像这样的二传手:
- (void) setToolName: (NSString*) toolName
{
if(_toolName== toolName)
return;
[_toolName release];
_toolName= [toolName copy];
}
这样你做得很好,你不应该关心setter参数的保留计数。如果它是一个具有未知保留计数的字符串文字,则该对象甚至不响应释放消息,因此它将为所有程序保持活动状态(不像它似乎有效,因为它避免了创建对象的开销)在运行时)。如果复制一个不可变对象(除非它像缓存的 NSNumber 或字符串文字一样),代码只会执行一个简单的赋值,并且保留计数会增加。
因此,如果你只遵循“我保留(或复制)我需要使用的规则,我会释放我不再需要使用的规则”,你做得很好,你不应该担心在特殊情况下会发生什么,比如字符串文字。