NSUserDefaults中的可变对象

时间:2013-06-01 18:54:56

标签: ios objective-c database nsmutablearray nsuserdefaults

我创建了一个简单的数据库并放入了NSUserDefaults。我的数据库是NSMutableArray,里面有字典和数组。当我从NSUSerDefaults创建NSMutableArray时,我无法向NSMutableArray中的可变对象添加任何对象。这是我的代码:

NSMutableArray *arrayOne = [NSMutableArray arrayWithContentsOfFile:[self createEditableCopyOfIfNeededWithFileName:@"Form.plist"]];

NSUserDefaults *ayarlar = [NSUserDefaults standardUserDefaults];

[ayarlar setObject:arrayOne forKey:@"form"];

NSMutableArray *arrayTwo = [NSMutableArray arrayWithArray:[[ayarlar objectForKey:@"form"] mutableCopy]];

[[[arrayTwo objectAtIndex:0] objectForKey:@"itemlar"] addObject:@"hop"];

这是错误:

'NSInternalInconsistencyException',原因:' - [__ NSCFArray insertObject:atIndex:]:发送到不可变对象的变异方法'

我该如何使这项工作?谢谢大家。

4 个答案:

答案 0 :(得分:4)

NSUserDefaults不是存储数据的正确位置。首先,它应该只用于非常少量的数据,例如设置。其次,它总是返回不可变对象,即使你设置了可变对象。制作第一个数组的可变副本没有用,因为只有数组才是可变的。

中,mutableCopy方法没有触及该数组内部的所有内容。

您应该使用NSPropertyListSerialization类从文件中读取和写入数据。在阅读时,您可以传递控制读取对象的可变性的选项。在那里,您需要传递NSPropertyListMutableContainers或NSPropertyListMutableContainersAndLeaves。

首先,所有容器(数组和字典)都是可变的。对于后者,叶子(即NSString和NSData对象)也是可变的。

根据数据集的大小,您可能应该使用真实数据库或核心数据。

答案 1 :(得分:2)

NSUserDefaults永远不会返回可变对象。

你的代码正在执行创建你能想到的可变数组的各种方式(即你正在创建一个你刚刚创建的可变副本的可变副本),但是,你只处理根容器项 - 不是内/叶项目。所以,当你在可变数组上执行objectForKey:@"itemlar"]时,你会得到一个不可变对象。

为了使它工作,你需要编写自己的方法,通过在所有级别创建可变副本的数组进行迭代和递归。

或者,您可以查看this之类的第三方选项,它会在NSUserDefaults的引擎下挖掘,以生成可变容器。

答案 2 :(得分:2)

NSUserDefaults和一般的属性列表不记录可变性。当从文件重新创建对象时,它可以构造为可变对象或不可变对象(对于具有该选项的类型,例如数组)。遗憾的是,NSUserDefaults没有为您提供API调用以直接获取不可变对象。

您有两个选项:(a)创建NSUserDefaults返回的对象的可变副本,或者(b)将对象自己存储为单独文件中的属性列表 - 这样您就可以将其读回直接变异。

对于(b)阅读Apple's docs - 它显示了如何处理可变性。

答案 3 :(得分:1)

您可以使用方法insertObject直接执行。

取代

[[[arrayTwo objectAtIndex:0] objectForKey:@"itemlar"] addObject:@"hop"];

使用此,

[arrayTwo insertObject:@"hop" atIndex:0];

这样就可以了,因为我已经测试过它也是有效的,因为你可以将它作为NSARRAY的不可变对象并保存到NSUSERDEFAULTS