【问题标题】:Getting "mutating method sent to immutable object" error获取“发送到不可变对象的变异方法”错误
【发布时间】:2011-04-19 01:34:47
【问题描述】:

我不知道是什么原因造成的。基本上,一些不同的“任务”在我的应用程序中相互冲突。当我按下一个按钮时,它运行这个代码就好了:

PalAppDelegate *dataCenter = (PalAppDelegate *)[[UIApplication sharedApplication] delegate];




[dataCenter.colourPalettesContainer addObject:[NSNumber numberWithInt:5]];

它可以根据我的喜好多次执行此操作。但是当我执行另一个任务时(还有一些导致这种情况发生),这涉及到这个代码,例如:

PalAppDelegate *dataCenter = (PalAppDelegate *)[[UIApplication sharedApplication] delegate];

[dataCenter.colourPalettesContainer removeObjectAtIndex:touchDownID];

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:dataCenter.colourPalettesContainer forKey:@"container"];
[prefs synchronize];

然后:

dataCenter.colourPalettesContainer = [prefs objectForKey:@"container"];

当我在此之后再次运行第一个代码时,它会导致崩溃并出现“发送到不可变对象的变异方法”错误。我怎样才能阻止这种情况?

编辑:所以我从下面的一些答案中发现了问题。有没有人有他们建议的不同方法来做这件事?

【问题讨论】:

  • 您的代码嵌套太深,人类难以理解。我建议您将 addObject 语句分成 5 或 10 个子语句。然后,如果有什么东西坏了,你就有机会找出它在哪里。
  • 它只是在我将保存添加到首选项行后才中断。它与我的深层嵌套数组无关。我会从中删除一些部分,以便于消化。
  • 您说“当我在此之后再次运行第一个代码时,它崩溃了” - 意思是嵌套数组中的某个地方,对吗?所以问题是你不知道分配问题在哪里。我通过许多痛苦的经历发现,像这样高度复杂的语句不会为您节省任何编译或性能时间,不会使代码更易于维护或调试,因此一开始就不值得花时间构建它们.我不是批评,只是提供一些友好的建议。
  • 坦率地说,答案没有多大意义。发布崩溃的回溯。
  • 在安德鲁编辑他的问题之前,我的回答更有意义。他正在向 NSUserDefaults 添加一堆可变集合,然后尝试在他取回的对象上调用 mutating 方法。目前写的问题并没有说清楚,但原来的问题。

标签: iphone objective-c nsmutablearray


【解决方案1】:

NSUserDefaults 返回一个不可变数组。加载备份时,您需要制作它的可变副本:

NSMutableArray *mutableArray = [[prefs objectForKey:@"container"] mutableCopy];
dataCenter.colourPalettesContainer = mutableArray;
[mutableArray release];

您可能还必须在数组内部进行一些操作,因为您将 NSMutableArrays 存储在其中。

【讨论】:

  • 我认为你是对的,因为实现该代码会导致我的应用程序内部出现一些非常奇怪的行为。有什么想法我需要在数组内部进行什么样的操作?
  • 我会改变它,以便您只持有不可变对象以使其更简单。对于数组,将它们保存为 NSArrays 而不是 NSMutableArrays。然后当你需要更改内容时,将其拉出,制作可变副本,添加/删除项目,然后将其添加回主数组。我也可能使 colourPalettesContainer 成为字典而不是数组。这样,您就可以用您的密钥记录价值。您还可以根据键进行替换,而不必担心索引。对于这种情况,订单看起来并不重要。
  • 为你+1,因为它也节省了我的时间,我不知道为什么会出现这个问题,即使我的数组是一个可变数组............跨度>
【解决方案2】:

NSUserDefaults 始终返回不可变对象,即使您存储的内容是可变的。要解决此问题,您需要制作一个可变副本。由于-mutableCopy返回调用者拥有的对象,所以需要(自动)释放:

dataCenter.colourPalettesContainer = [[[prefs objectForKey:@"container"] mutableCopy] autorelease];

编辑)我不久前发布了一些-mutableDeepCopy NSArray & NSDictionary methods,以回应另一个问题。如果您的问题涉及更深层次的集合嵌套,并且您需要它们全部是可变的,这可能会有所帮助。

【讨论】:

    【解决方案3】:

    从数组的特定索引中删除对象。 (斯威夫特 3.0)

    let fullArray : NSArray = Userdefaults().value(forKey: "YOUR_ARRAY_STRING") as! NSArray
    var mutableArray : [AnyObject] = fullArray as [AnyObject]
    mutableArray.remove(at: INDEX_TO_REMOVE) //Eg: mutableArray.remove(at: 0)
    mutableArray.append(ARRAY_TO_APPEND)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-13
      • 2016-11-17
      • 1970-01-01
      相关资源
      最近更新 更多