在常量和非常量字符串之间交替时,NSString的最佳分配

时间:2021-11-06 16:04:35

I would like some help better understanding the memory characteristics of Strings in Cocoa. The app I am working with uses one view controller and n tool objects. The View controller lives for the life of the program but the tool objects are allocated and released.

我想帮助更好地理解Cocoa中字符串的内存特性。我正在使用的应用程序使用一个视图控制器和n个工具对象。 View控制器在程序的生命周期中存在,但工具对象已分配和释放。

Suppose I have a string toolName_ and in my implementation I configure the incoming tool object: if the object does not have a tool name, I want to set the toolName_ string to @"not set". If the tool has a name I want to set the string to the name of the tool.

假设我有一个字符串toolName_,在我的实现中我配置了传入的工具对象:如果对象没有工具名称,我想将toolName_字符串设置为@“not set”。如果该工具有一个名称,我想将该字符串设置为该工具的名称。

I would like to know the proper way to store the incoming value into the toolName_ given that sometimes this will be an allocated object and sometimes this will be a constant string.

我想知道将传入值存储到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;
    }

 }

Advice appreciated.

1 个解决方案

#1


1  

I highly suggest to (possibly) use ARC, and if you can't use it (or maybe you just want to understand how memory management works?), to don't send retain and release messages from outside the class. Instead you should do this in the accessors.

我强烈建议(可能)使用ARC,如果你不能使用它(或者你只是想了解内存管理是如何工作的?),不要发送来自课外的保留和释放消息。相反,你应该在访问器中执行此操作。

So you should create a retain or copy property (usually with immutable strings is preferable to use copy, because they may be assigned to mutable strings, so making invalid the assumption that you are working with an immutable - thus thread safe - property).

因此,您应该创建一个retain或copy属性(通常使用不可变字符串比使用copy更好,因为它们可能被分配给可变字符串,因此假设您使用的是不可变的 - 因此是线程安全的 - 属性)。

So in your case I suggest a setter like this one:

所以在你的情况下,我建议像这样的二传手:

- (void) setToolName: (NSString*) toolName
{
    if(_toolName== toolName)
        return;
    [_toolName release];
    _toolName= [toolName copy];
}

This way you're doing it fine, you shouldn't be concerned about what is the retain count of the setter argument. In case it is a string literal which has an unknown retain count, the object does not even respond to a release message, so it will stay alive for all the program (unlike it seems it is efficient because it avoids the overhead of creating an object at runtime). If you copy an immutable object (unless it something like a cached NSNumber, or a string literal), the code just does a simple assignment and the retain count gets increased.

这样你做得很好,你不应该关心setter参数的保留计数。如果它是一个具有未知保留计数的字符串文字,则该对象甚至不响应释放消息,因此它将为所有程序保持活动状态(不像它似乎是有效的,因为它避免了创建对象的开销)在运行时)。如果你复制一个不可变对象(除非它像缓存的NSNumber或字符串文字),代码只是做一个简单的赋值,保留计数增加。

So if you just follow the rule of "I retain (or copy) what I need to use, I release what I don't need to use anymore", you're doing it fine and you shouldn't worry about what happens in particular case like with string literals.

因此,如果你只是遵循“我保留(或复制)我需要使用的规则,我会释放我不再需要使用的”,你做得很好,你不应该担心会发生什么特殊情况,如字符串文字。

#1


1  

I highly suggest to (possibly) use ARC, and if you can't use it (or maybe you just want to understand how memory management works?), to don't send retain and release messages from outside the class. Instead you should do this in the accessors.

我强烈建议(可能)使用ARC,如果你不能使用它(或者你只是想了解内存管理是如何工作的?),不要发送来自课外的保留和释放消息。相反,你应该在访问器中执行此操作。

So you should create a retain or copy property (usually with immutable strings is preferable to use copy, because they may be assigned to mutable strings, so making invalid the assumption that you are working with an immutable - thus thread safe - property).

因此,您应该创建一个retain或copy属性(通常使用不可变字符串比使用copy更好,因为它们可能被分配给可变字符串,因此假设您使用的是不可变的 - 因此是线程安全的 - 属性)。

So in your case I suggest a setter like this one:

所以在你的情况下,我建议像这样的二传手:

- (void) setToolName: (NSString*) toolName
{
    if(_toolName== toolName)
        return;
    [_toolName release];
    _toolName= [toolName copy];
}

This way you're doing it fine, you shouldn't be concerned about what is the retain count of the setter argument. In case it is a string literal which has an unknown retain count, the object does not even respond to a release message, so it will stay alive for all the program (unlike it seems it is efficient because it avoids the overhead of creating an object at runtime). If you copy an immutable object (unless it something like a cached NSNumber, or a string literal), the code just does a simple assignment and the retain count gets increased.

这样你做得很好,你不应该关心setter参数的保留计数。如果它是一个具有未知保留计数的字符串文字,则该对象甚至不响应释放消息,因此它将为所有程序保持活动状态(不像它似乎是有效的,因为它避免了创建对象的开销)在运行时)。如果你复制一个不可变对象(除非它像缓存的NSNumber或字符串文字),代码只是做一个简单的赋值,保留计数增加。

So if you just follow the rule of "I retain (or copy) what I need to use, I release what I don't need to use anymore", you're doing it fine and you shouldn't worry about what happens in particular case like with string literals.

因此,如果你只是遵循“我保留(或复制)我需要使用的规则,我会释放我不再需要使用的”,你做得很好,你不应该担心会发生什么特殊情况,如字符串文字。