【问题标题】:NSString and NSMutableString methods and casting via mutableCopyNSString 和 NSMutableString 方法以及通过 mutableCopy 进行强制转换
【发布时间】:2014-10-29 13:01:38
【问题描述】:

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

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

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

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

但是为什么 NSMutableString 中的大写字符串没有像 "-(NSMutableString*) capitalizedString" 那样重载呢?

如果是这样,我们可以简单地编写以下内容而没有警告:

foobar = [foobar capitalizedString]; // line 2

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

【问题讨论】:

  • 这是因为你一开始就有一个 NSMutableString 是愚蠢的。 NSString* foobar = [@"foobar" capitalizedString] 工作得很好。

标签: objective-c nsstring


【解决方案1】:

因此,为了将其影响为 NSMutableString,您必须通过 mutableCopy “重铸”它

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

但是为什么 NSMutableString 中的大写字符串没有像 "-(NSMutableString*) capitalizedString" 那样重载呢?

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

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

值得注意的是,Swift 确实有重载,而您所描述的可以在 Swift 中完成(尽管它会破坏类型推断,所以在大多数情况下它可能会很烦人)。但是重载是 Swift 认为值得添加的东西。 ObjC 只是没有它们。

【讨论】:

    【解决方案2】:

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

    @property(readonly, copy) NSString *capitalizedString
    

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

    【讨论】:

      【解决方案3】:

      [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 中使用可变对象并不常用/不需要。

      【讨论】:

      • 我将 NSString 视为“const char* / const std::string”,将 NSMutableString 视为“char */std::string”。在您发表评论后,我进行了测试,但似乎并非如此:可以修改 NSString。
      • 一个NSString不能被修改,一个新的(修改的实例)可以分配给同一个指针。这是典型的模式。指针不是constNSString 实例是不可变的。可以在 Objective-C 中创建 const 指针。
      • @BlakBat:你的观点不正确。有可变对象和不可变对象。很少使用可变对象。阅读 Objective-C 的一个很好的介绍。提示:它与 C++ 不同。
      • @gnasher729,可变对象在 ObjC 中非常常见。 NSMutableString 并不常见,但 NSMutableArray 无处不在。不过,正如@Zaph 指出的那样,C++ 的const 并不是考虑NSString 的好方法。 NSString 只是一个类,NSMutableString 只是它的一个子类。它们没有编译器强制的可变性语义。 NSString 恰好没有变异方法。
      • 值得注意的是NSMutableString ISA NSString。这意味着NSString 有可能在你背后发生变异。这是 ObjC 开发人员实际上要防御的东西(我们对通过的 NSString 对象进行防御性调用 copy)。
      猜你喜欢
      • 1970-01-01
      • 2017-01-23
      • 2011-02-23
      • 1970-01-01
      • 2016-11-07
      • 2015-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多