【问题标题】:Objective-C: Copy Array, Modify Element (Object) in the Copy ONLYObjective-C:复制数组,仅在复制中修改元素(对象)
【发布时间】:2013-05-31 21:28:22
【问题描述】:

在问这个问题之前,我已经阅读了许多 SO 帖子,我猜这个答案就在某个地方,但我没有看到。我是 Objective-C 的新手,我正在尝试做一个我无法理解的(看似)简单的操作。

一般的想法是我有一个NSArray 填充对象(特别是UIImageView 类型)。我想复制那个数组,我已经做了很多方法(都成功)。

复制后,我现在有两个数组。我想修改一个对象,比如在索引 2 处,ONLY 在副本中。

目前看来,因为副本只是复制引用(或指针),更改索引 2 处的对象将同时更改副本原件。

这有意义吗?

NSArray *originalArray = @[object1, object2];

我尝试复制此数组的方式,以便实现我想要的:

NSMutableArray *originalArrayCopy = [NSMutableArray arrayWithArray:originalArray];

NSArray *originalArrayCopy = [originalArray copy];

NSMutableArray *originalArrayCopy = [[NSMutableArray alloc] initWithArray:originalArray];

似乎在每种情况下,从副本中修改对象也会在原始对象中修改它。

注意:虽然NSArray 显然是不可变的,但我的原始数组中的对象可变的。

【问题讨论】:

    标签: objective-c nsmutablearray nsarray


    【解决方案1】:

    如果你的数组元素符合NSCopying 协议,你可以这样做:

    NSMutableArray *copy = [[NSMutableArray alloc] initWithArray:originalArray copyItems:YES];
    

    这具有向原始数组的每个元素发送copy 的效果,将副本存储在新数组中。

    如果每个元素在收到copy 消息时返回一个新的、可变的副本,这很好。但是,一些 Foundation 类(如 NSMutableArrayNSMutableString)在收到 copy 消息时会返回不可变副本。如果您的元素属于此类,则需要发送mutableCopy 消息。

    没有内置的公共消息可以做到这一点。您可以像这样手动操作:

    NSMutableArray *copy = [[NSMutableArray alloc] initWithCapacity:originalArray.count];
    for (id element in originalArray) {
        [copy addObject:[element mutableCopy]];
    }
    

    【讨论】:

    • 是的,第二种解决方案是有道理的。但是,我在我的问题中犯了一个错误,因为我没有指定原始数组中的元素是 UIImageView 类型。我知道这会让事情变得更具挑战性。尝试第二个解决方案时,我收到错误:NSInvalidArgumentException [UIImageView mutableCopywithZone:]
    • 每个 UIImageView 对象都是我的一个类的属性。
    • 请编辑您的问题以解释您为什么要复制图像视图。您会将它们放在视图层次结构中的什么位置?
    • 好的,谢谢。虽然我的问题仍然适用,但我“需要”复制 UIImageView 实例的方式只是我的设计缺陷。
    • 第二种解决方案对我有用。但我仍然怀疑当我们使用 NSMutableArray*copy=[originalArray mutableCopy]; 时它不起作用;
    【解决方案2】:

    这会将第一个 NSArray 的深层复制到第二个 NSMutableArray:

    NSArray *firstArray = [NSArray arrayWithObjects:@"foo", @"bar",nil];
    NSMutableArray *secondArray = [[NSMutableArray alloc]initWithArray:firstArray copyItems:YES];
    

    【讨论】:

      【解决方案3】:

      只要您要复制的对象实现 NSCoding 协议

      (void)encodeWithCoder:(NSCoder *)encoder;
      (id)initWithCoder:(NSCoder *)decoder;
      

      你可以用这种方式对任何对象进行深拷贝

      NSArray *originalArray = @[object1, object2];
      NSMutableArray *deepCopy = [NSkeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject: originalArray]];
      

      【讨论】:

        【解决方案4】:

        是的,所有这些只会复制数组。您复制的数组仍将引用相同的对象。

        我不认为(或只是不知道如何)您可以一次性复制所有包含的对象。我想您将不得不遍历原始数组中的对象,复制每个对象并将其副本添加到新创建的最初为空的可变数组中。 如何复制这些对象很大程度上取决于这些对象的性质和复制它们的目的。

        是的,不可变数组中的对象也没有理由不可变。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-20
          • 1970-01-01
          • 2019-06-11
          • 1970-01-01
          • 2021-05-11
          相关资源
          最近更新 更多