NSString和NSMutableString方法并通过mutableCopy进行转换

时间:2014-10-29 13:01:39

标签: objective-c nsstring

来自C ++背景,我很惊讶我必须编写以下代码以避免警告:

NSMutableString *foobar = [@"foobar" mutableCopy]; // line 1
foobar = [[foobar capitalizedString] mutableCopy]; // line 2

第1行对我来说似乎很正常:你不能直接将const字符串转换为字符串。

第2行让我感到困惑:capitalizedString是一个属于NSString并返回NSString的方法。因此,为了将其影响到NSMutableString,您必须重新制作"它通过mutableCopy。

但是为什么在NSMutableString中没有重写大写字符串,例如&#34 ;-(NSMutableString *)capitalizedString" ?

如果是这种情况,我们可以简单地写下以下内容而不发出警告:

foobar = [foobar capitalizedString]; // line 2

PS:我知道我可以在一个中写两行,但这只是一个例子。

3 个答案:

答案 0 :(得分:2)

  

因此,为了将它影响到NSMutableString,你必须通过mutableCopy“重新”它

mutableCopy不是像C ++中那样的“重铸”。它创建了一个可变副本。在ObjC有重铸,这不是它。这种区别很重要,因为“重铸”表明你只是采用一个对象而只是以不同的方式对待它。 mutableCopy创建一个具有内存管理含义的新对象。 (这些现在主要由ARC处理,但它们对于理解正在发生的事情仍然很重要。)

  

但为什么在NSMutableString中没有像capitalizeString那样重载“ - (NSMutableString *)capitalizedString”?

Objective-C没有重载。所以这是不可能的,即使它是可取的。它是否真正令人满意是一个有趣的问题。在某些用例中,它可能更方便。在其他用例中它会不太方便(不可变字符串有可变优化可用的可变字符串丢失,所以如果我想要那些优化,我将不得不再次复制字符串以使其不可变)。但这没有实际意义;过载是不可能的。因此,要获得您所要求的内容,您必须创建-mutableCapitalizedString,就像我们copymutableCopy一样。 (这很愚蠢,因为capitalizedString非常罕见。)

正如@Zaph指出的那样,NSMutableString在ObjC中有点不常见。也就是说,您的问题也适用于-sortedArrayUsingSelector:,因此基本问题是有效的。

值得注意的是,Swift确实有重载,你所描述的内容可以在Swift中完成(尽管它会打破类型推断,所以在大多数情况下它可能会很烦人)。但重载是Swift认为有价值的补充。 ObjC只是没有它们。

答案 1 :(得分:1)

根据Apple Documentation capitalizedString方法的内部实现如下所示,其中包含readonlycopy属性。

@property(readonly, copy) NSString *capitalizedString

因此,如果调用capitalizedString方法,它将返回NSString对象。因此,为了将其影响到NSMutableString对象,需要使用mutableCopy

答案 2 :(得分:1)

[foobar capitalizedString]返回NSStringfoobar已声明为NSMutableString,因此需要创建一个可变版本才能进行分配。

NSString *foobar = @"foobar";
foobar = [foobar capitalizedString];
// Create a new instance `NSString` instance and assigns it to the same `NSString` pointer `foobar`.

为什么要使用NSMutableString?在Objective-C中,使用可变对象并不常用/需要。