2014-01-09 46 views
0

將一個空的NSMutableArray寫入磁盤,然後再讀取它,它變成一個不可變的對象。
但是,如果NSMutableArray不是空的,它不會。如何解釋?
這裏是代碼:從plist讀取的空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'" 
+0

將數據寫入爲JSON。用NSJSONSerialization回讀,指定'NSJSONReadingMutableContainers'選項。 –

+0

僅供參考 - 您的'/ tmp'路徑只會在模擬器中有效,或者可能是越獄的iOS設備。不要在「真實」代碼中使用這樣的路徑。 – rmaddy

回答

3

的這兩行代碼:

NSMutableArray *testReadLists = [NSMutableArray array]; 
[testReadLists setArray:[NSArray arrayWithContentsOfFile:@"/tmp/testLists"]]; 

給你不可變對象的可變數組。您可以添加和刪除testReadLists中的對象,但是您從該數組中獲得的所有內容(最初從plist中加載)都是不可變的。

更新 - 我即將發佈有關解決方案的信息,但Vivek的答案描述了我要說的話。

+0

'[[NSArray arrayWithContentsOfFile:@「/ tmp/testLists」] mutableCopy]'更容易 –

+4

爲什麼不只是'[NSMutableArray arrayWithContentsOfFile:@「/ tmp/testLists」];'? – dreamlax

1

有沒有這個測試自己,但你可能想先讀入的plist一個NSData,然後通過做+[NSPropertyListSerialization propertyListWithData:options:format:error:],在指定選項參數NSPropertyListMutableContainers(DOC蘋果here

注獲得實際的數組這應該給你一個完整的可變容器層次結構(一個包含NSMutableDictionaries的NSMutableArray,等等)。如果你想要的只是一個NSMutableArray在層次結構中的一個特定級別,那麼其他公佈的解決方案/評論可能是一個更合適的解決方案。

+0

[NSMutableArray arrayWithContentsOfFile:file]呢?我改變了這一點,它現在起作用 – bandw

+0

@bandw回覆評論(編輯)答案。 – Vivek

+0

我已經測試了3個級別(包含NSMutableDictionary的NSMutableDictionary包含NSMutableArray)用[NSMutableArray arrayWithContentsOfFile:file]讀取plist數據。 NSMutableArray中最內部的部分是可變的。 [NSMutableArray arrayWithContentsOfFile:]也給出了可變容器的完整層次結構,它比讀取NSData更簡單,並使用+ [NSPropertyListSerialization propertyListWithData:options:format:error:] – bandw

0

直接從屬性列表中讀取的對象是總是不可變。你可以從它們創建一個可變對象,但對象本身是不可變的。這些行是問題:

NSMutableDictionary *testReadList = [testReadLists objectAtIndex:0]; 
NSMutableArray *testReadItems = [testReadList objectForKey:@"list_items"]; 

testReadList是可變數組testReadLists中第一個對象,但對象本身仍然是儘管中testReadList聲明類型爲NSMutable*不變。同樣,即使您將其分配給testReadItems(聲明爲NSMutableArray*),您從objectForKey:呼叫返回的對象也是NSArray的一個實例。您可以通過在添加新項目前簡單製作可變副本來避免此問題:

NSMutableArray *testReadItems = [[testReadList objectForKey:@"list_items"] mutableCopy]; 
相關問題