Ios 从plist读取的空NSMutableArray成为不可变对象

Ios 从plist读取的空NSMutableArray成为不可变对象,ios,iphone,objective-c,Ios,Iphone,Objective C,将空NSMutableArray写入磁盘,然后将其读回,它将成为不可变对象。 但是,如果NSMutableArray不是空的,则不会为空。怎么解释呢? 代码如下: NSMutableArray *testItems1 = [NSMutableArray array]; NSMutableDictionary *testList1 = [NSMutableDictionary dictionaryWithObjectsAndKeys:testItems1, @"list_items", @"lis

将空NSMutableArray写入磁盘,然后将其读回,它将成为不可变对象。
但是,如果NSMutableArray不是空的,则不会为空。怎么解释呢?
代码如下:

NSMutableArray *testItems1 = [NSMutableArray array];
NSMutableDictionary *testList1 = [NSMutableDictionary dictionaryWithObjectsAndKeys:testItems1, @"list_items", @"list1", @"list_name", nil];

NSMutableArray *testItems2 = [NSMutableArray arrayWithObjects:@"item11", @"item22", nil];
NSMutableDictionary *testList2 = [NSMutableDictionary dictionaryWithObjectsAndKeys:testItems2, @"list_items", @"list2", @"list_name", nil];

NSMutableArray *testLists = [NSMutableArray arrayWithObjects:testList1, testList2, nil];

[testLists writeToFile:@"/tmp/testLists" atomically:YES];

NSMutableArray *testReadLists = [NSMutableArray array];
[testReadLists setArray:[NSArray arrayWithContentsOfFile:@"/tmp/testLists"]];
NSMutableDictionary *testReadList = [testReadLists objectAtIndex:0];
NSMutableArray *testReadItems = [testReadList objectForKey:@"list_items"];
[testReadItems addObject:@"item3"]; // Crashes here: "*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'"

这两行代码:

NSMutableArray *testReadLists = [NSMutableArray array];
[testReadLists setArray:[NSArray arrayWithContentsOfFile:@"/tmp/testLists"]];
为您提供不可变对象的可变数组。您可以从
testreadlist
中添加和删除对象,但从该数组(最初从plist加载)获得的所有内容都是不可变的


更新-我正要发布有关解决方案的信息,但Vivek的回答描述了我要说的内容。

这两行代码:

NSMutableArray *testReadLists = [NSMutableArray array];
[testReadLists setArray:[NSArray arrayWithContentsOfFile:@"/tmp/testLists"]];
为您提供不可变对象的可变数组。您可以从
testreadlist
中添加和删除对象,但从该数组(最初从plist加载)获得的所有内容都是不可变的


更新-我正要发布有关解决方案的信息,但Vivek的回答描述了我要说的内容。

我自己还没有测试过,但您可能想先将plist读入NSData,然后通过执行
+[NSPropertyListSerialization propertyListWithData:options:format:error:
获得实际数组,在选项参数(apple doc)中指定
nsPropertyListMetableContainers


注意,这将为您提供可变容器的完整层次结构(包含NSMutableDictionary等的NSMutableArray)。如果您只需要层次结构中某一特定级别的NSMutableArray,那么其他发布的解决方案/注释可能是更合适的解决方案。

我自己还没有测试过这一点,但您可能希望首先将plist读入NSData,然后通过执行
+[NSPropertyListSerialization propertyListWithData:选项:格式:错误:
,在选项参数(apple文档)中指定
NSPropertyListMutableContainers


注意:这将为您提供可变容器的完整层次结构(包含NSMutableDictionary的NSMutableArray,等等)。如果您只需要层次结构中某一特定级别的NSMutableArray,则其他发布的解决方案/注释可能是更合适的解决方案。

直接从属性列表读取的对象始终是不可变的。您可以从它们创建可变对象,但对象本身是不可变的。这些行是问题所在lem:

NSMutableDictionary *testReadList = [testReadLists objectAtIndex:0];
NSMutableArray *testReadItems = [testReadList objectForKey:@"list_items"];
testReadList
是可变数组
testReadList
中的第一个对象,但是该对象本身仍然是不可变的,尽管
testReadList
的声明类型是
NSMutable*
。同样,从
objectForKey:
调用返回的对象是
NSArray
的实例>即使将其分配给声明为
NSMutableArray*
testReadItems
,也可以通过在添加新项之前创建可变副本来避免问题:

NSMutableArray *testReadItems = [[testReadList objectForKey:@"list_items"] mutableCopy];

直接从属性列表读取的对象始终是不可变的。您可以从它们创建可变对象,但对象本身是不可变的。问题在于:

NSMutableDictionary *testReadList = [testReadLists objectAtIndex:0];
NSMutableArray *testReadItems = [testReadList objectForKey:@"list_items"];
testReadList
是可变数组
testReadList
中的第一个对象,但是该对象本身仍然是不可变的,尽管
testReadList
的声明类型是
NSMutable*
。同样,从
objectForKey:
调用返回的对象是
NSArray
的实例>即使将其分配给声明为
NSMutableArray*
testReadItems
,也可以通过在添加新项之前创建可变副本来避免问题:

NSMutableArray *testReadItems = [[testReadList objectForKey:@"list_items"] mutableCopy];

以JSON格式写入数据。使用NSJSONSerialization进行读取,指定
NSJSONReadingMutableContainers
选项。仅供参考-到
/tmp
的路径仅在模拟器或越狱iOS设备中有效。不要在“real”中使用此类路径代码。以JSON格式写入数据。使用NSJSONSerialization读回,指定
NSJSONReadingMutableContainers
选项。仅供参考-到
/tmp
的路径仅在模拟器或越狱iOS设备中有效。不要在“真实”代码中使用此类路径。
[[NSArray arrayWithContentsOfFile:@”/tmp/testlist]mutableCopy]
更容易为什么不仅仅是
[NSMutableArrayWithContentsOfFile:@/tmp/TestList”];
[NSArrayWithContentsOfFile:@/tmp/TestList”]mutableCopy]
更容易为什么不仅仅是
[NSMutableArrayWithContentsOfFile:@/tmp/TestList”];
[NSMutableArrayWithContentsOfFile:file]呢?我更改了此选项,现在可以使用了。我已测试了3个级别(NSMutableDictionary包含NSMutableDictionary包含NSMutableArray包含NSMutableArray)使用[NSMutableArray arrayWithContentsOfFile:file]读取的列表数据。NSMutableArray中最内部的是可变的。[NSMutableArrayWithContentsOfFile:]它还提供了可变容器的完整层次结构,比读取NSData并使用+[NSPropertyListSerialization propertyListWithData:options:format:error:]更简单[NSMutableArray arrayWithContentsOfFile:file]怎么样?我改成了这个,现在它可以工作了我已经测试了3个级别(NSMutableDictionary包含NSMutableDictionary包含NSMutableArray)使用[NSMutableArray arrayWithContentsOfFile:file]读取列表数据。NSMutableArray内部的大部分是可变的。[NSMutableArrayWithContentsOfFile:]还提供了可变容器的完整层次结构,比读取NSData和使用更简单+[NSPropertyListSerialization propertyListWithData:选项:格式:错误:]