4

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

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

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

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

所以我的问题是,当我调用stringByAppendingString一个字符串而不是明确的 NSStringNSMutableString 时,隐含地发生了什么?例如,在我上面的例子中,字典中某个键的值。这样做是错误的,我应该做如下的事情吗?

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

4 回答 4

5

我读到如果你在 NSString 上使用 stringByAppendingString,你最终会出现泄漏,因为与初始 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 相比较,Java 有一个 String 类和一个完全独立的 BufferedString 类。

于 2011-03-04T17:01:53.847 回答
3

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

NSString *string3 = [string1 stringByAppendingString:string2];

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

[mutableString1 appendString:string2];

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

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

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

于 2011-03-04T18:00:10.033 回答
3

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

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

于 2011-03-04T17:01:03.083 回答
0

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

  1. 如果你拥有一个对象,你需要在某个时候释放或自动释放它。
  2. 如果您使用 alloc、new 或 copy 方法创建对象,或者如果您保留它,则您拥有一个对象。

确保您阅读了 Apple 的内存管理规则

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

于 2011-03-04T17:05:00.467 回答