NSString vs NSMutableString with stringByAppendingString

时间:2011-03-04 16:46:39

标签: iphone string nsstring uilabel nsmutablestring

所以,我很确定如果我打算经常操作字符串,比如使用stringByAppendingString,我应该使用NSMutableString类型的变量。

但是,如果我做这样的事情呢?

UILabel *someLabel = [[UILabel alloc] init];
[someLabel setText: [[someDictionary objectForKey:@"some_key"] stringByAppendingString:@"some other string"];

我读到如果在NSString上使用stringByAppendingString,最终会出现泄漏,因为与初始NSString关联的指针会移动,指向由追加创建的新字符串,而使用NSMutableString,指针总是指向那个可变的字符串。

所以我的问题是,当我在一个字符串上调用stringByAppendingString但是没有明确地表示NSString 一个NSMutableString时,会发生什么?比如,在我上面的例子中,字典中某些键的值。这样做是错的,我应该做下面的事情吗?

[[[NSMutableString stringWithString:[someDictionary objectForKey:@"some_key"]] stringByAppendingString:@"some other string"]]

4 个答案:

答案 0 :(得分:5)

  

如果您使用,我会读到   stringByAppendingString上   NSString,你最终会泄漏   因为指针与之相关联   最初的NSString移动,   指向由...创建的新字符串   追加,而与   NSMutableString,你的指针总是   指向那个可变的字符串。

这听起来像是一个没有完全掌握内存管理内容的人的建议。当然,[NSString stringByAppendingString]会返回一个新字符串。但你用新字符串做什么取决于你。你可以通过粗心的方式将结果重新分配给保留的属性来导致内存泄漏,如下所示:

myStringProperty = [myStringProperty stringByAppendingString:@" more bits"];

正确的形式是使用self,如下所示:

self.myStringProperty = [myStringProperty stringByAppendingString:@" more bits"];

遵循可可记忆指南。

至于字典和其他集合类型:根据您知道的类型,适当地处理字典中的内容。如果您拉出一个实际上是NSString的对象,但尝试将其用作NSMutableString,您的应用程序将会崩溃(“未找到选择器”或类似)。因此,在这种情况下,您需要从NSString创建一个新的NSMutableString。

有趣的提示:Apple选择将NSMutableString作为NSString的子类。关于这一点似乎是不明智的 - 如果某些东西看起来是不可变的,因为它有类型NSString,我希望它是不可变的! (但实际上它可能是NSMutableString。)与Java相比,它有一个String类和一个完全独立的BufferedString类。

答案 1 :(得分:3)

我一直是[NSString stringWithFormat@"%@%@", a, b];的粉丝,因为那时你明显得到一个新的自动释放字符串,并且可以正确处理“a”和“b”。

使用[someDictionary objectForKey:@"some_key"],您将获得最初放入该字典的对象类型。所以盲目地调用stringByAppendingString而不知道该字典中的内容似乎是一个坏主意。

答案 2 :(得分:3)

-stringByAppendingString将返回一个与所涉及的两个字符串不同的新NSString。换句话说:

NSString *string3 = [string1 stringByAppendingString:string2];

string3是一个全新的字符串。 string1根本没有改变,它的内存位置或内容没有任何变化。那个告诉你的人可能只是误解了发生的事情。

[mutableString1 appendString:string2];

在这种情况下,mutableString1仍然指向同一个对象,但该对象的内容已被更改为包含string2。

要记住的最后一件事是,如果您使用可变字符串,则应该小心共享对它的引用。如果将可变字符串传递给某个函数,该函数保留指向该可变字符串的指针,然后您的代码在将来的某个时刻更改该可变字符串,则另一个引用指向完全相同的对象,这意味着其他代码将看到变化也是如此。如果这就是你想要的,那很好,但如果没有,你一定要小心。

帮助避免此问题的一种方法是声明NSStrings的@property语句为" copy"而不是"保留"。这将在您的属性中设置它之前复制您的可变字符串,并且-copy方法隐式地为您提供了一个NON-mutable版本,因此它将创建NSMutableString的NSString副本。

答案 3 :(得分:0)

如果您遵循内存管理规则,那么使用stringByAppendingString就可以了。简而言之:

  1. 如果您拥有一个对象,则需要在某个时刻释放或自动释放它。
  2. 如果使用alloc,new或copy方法创建对象,或者保留对象,则拥有对象。
  3. 请务必阅读Apple的Memory Management Rules

    在您提问的第一个代码示例中,您没有在所涉及的任何NSStrings上使用alloc,new,copy或retain,因此您无需执行任何操作来释放它。如果在示例中包含的代码之外,您在任何NSStrings上使用alloc,new,copy或retain,则需要确保它们稍后发布。