Objective c 理解拷贝和可变拷贝

Objective c 理解拷贝和可变拷贝,objective-c,copy,semantics,mutable,Objective C,Copy,Semantics,Mutable,考虑以下几点: // BaseClass is both NSCopyable and NSMutableCopyable @interface MyClass : BaseClass { // a bunch of properties } // x is a MyClass* local variable in a method MyClass *a = [x copy]; // a is a strong reference to an immutable cop

考虑以下几点:

// BaseClass is both NSCopyable and NSMutableCopyable
@interface MyClass : BaseClass {
    // a bunch of properties
}

// x is a MyClass* local variable in a method
MyClass *a = [x copy];         // a is a strong reference to an immutable copy?
MyClass *b = [x mutableCopy];  // b is a strong reference to a mutable copy?
问题:

  • 我可以对a的IVAR进行任何更改吗?如果没有,如果我尝试更改任何IVAR会发生什么?我是否会得到不确定的行为,例如,有时有效,有时无效,内存损坏,或者编译器完全禁止它

  • 我可以对b的IVAR进行任何更改吗

  • 简短回答
  • 对。如果可以访问iVar,则不会出现内存损坏和编译错误
  • 与1相同
  • 长话短说

    易变和不可变拷贝是在Apple的基础类中发现的核心概念之一,如<代码> NScord或<代码> NSArray < /代码>。如协议中所述,实现了“不可变vs可变”概念的类必须为

    copyWithZone:
    返回不可变对象

    但是,编译器或内存保护并不强制执行对象的不可变性,但类设计器必须设计类,使其在收到
    copy
    消息时返回不可变对象

    在您的例子中,实现这种功能的常用方法是使
    MyClass
    不可变,并将其子类化为
    MyMutableClass
    并使其可变。您的呼叫站点应该如下所示:

    MyClass *a = [x copy];         
    MyMutableClass *b = [x mutableCopy]; 
    

    请注意,实现可变/不可变有时非常繁琐,因此请确保您有足够的理由实现此类功能。

    现在假设我正在从SpriteKit库复制一个类,如SKNode,该库实现NSCopying,但不实现NSMutableCopying。当我在SKNode*上调用copy而不是mutableCopy时,如果它没有实现nsmutablecopy,我是否假设它返回的对象是可变的?根据您上面的解释,我的理解是,除非有一个类的可变版本,例如SKMutableNode,否则我可以假设我可以修改返回的副本?对于常见场景,您可以假设。但是,这实际上取决于实现,因为
    NSCopying
    合同没有说明这种情况下的任何内容,例如,它可能是深度克隆或浅层克隆,或者其他任何内容。我建议,如果文档(例如SpriteKit文档)没有阐明
    复制
    方法的性质,那么常识在这里非常有用。