来自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:我知道我可以在一个中写两行,但这只是一个例子。
答案 0 :(得分:2)
因此,为了将它影响到NSMutableString,你必须通过mutableCopy“重新”它
mutableCopy
不是像C ++中那样的“重铸”。它创建了一个可变副本。在ObjC有重铸,这不是它。这种区别很重要,因为“重铸”表明你只是采用一个对象而只是以不同的方式对待它。 mutableCopy
创建一个具有内存管理含义的新对象。 (这些现在主要由ARC处理,但它们对于理解正在发生的事情仍然很重要。)
但为什么在NSMutableString中没有像capitalizeString那样重载“ - (NSMutableString *)capitalizedString”?
Objective-C没有重载。所以这是不可能的,即使它是可取的。它是否真正令人满意是一个有趣的问题。在某些用例中,它可能更方便。在其他用例中它会不太方便(不可变字符串有可变优化可用的可变字符串丢失,所以如果我想要那些优化,我将不得不再次复制字符串以使其不可变)。但这没有实际意义;过载是不可能的。因此,要获得您所要求的内容,您必须创建-mutableCapitalizedString
,就像我们copy
和mutableCopy
一样。 (这很愚蠢,因为capitalizedString
非常罕见。)
正如@Zaph指出的那样,NSMutableString
在ObjC中有点不常见。也就是说,您的问题也适用于-sortedArrayUsingSelector:
,因此基本问题是有效的。
值得注意的是,Swift确实有重载,你所描述的内容可以在Swift中完成(尽管它会打破类型推断,所以在大多数情况下它可能会很烦人)。但重载是Swift认为有价值的补充。 ObjC只是没有它们。
答案 1 :(得分:1)
根据Apple Documentation capitalizedString
方法的内部实现如下所示,其中包含readonly
和copy
属性。
@property(readonly, copy) NSString *capitalizedString
因此,如果调用capitalizedString
方法,它将返回NSString
对象。因此,为了将其影响到NSMutableString
对象,需要使用mutableCopy
答案 2 :(得分:1)
[foobar capitalizedString]
返回NSString
但foobar
已声明为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中,使用可变对象并不常用/需要。