7

我使用NSMutableDictionary和打這個錯誤「變異方法發送到不可變對象」:儘管對象是的NSMutableDictionary

'NSInternalInconsistencyException', reason: '-[__NSCFDictionary removeObjectForKey:]: mutating method sent to immutable object' 

下面的代碼:

// Turn the JSON strings/data into objects 
    NSError *error; 
    NSMutableDictionary *invoiceDictFromReq = [[NSMutableDictionary alloc] init]; 
// invoiceDictFromReq = (NSMutableDictionary *)[NSJSONSerialization JSONObjectWithData:[request responseData] options:kNilOptions error:&error]; 
    invoiceDictFromReq = [NSMutableDictionary dictionaryWithDictionary:[NSJSONSerialization JSONObjectWithData:[request responseData] options:kNilOptions error:&error]]; 

NSLog(@"invoiceDictFromReq count: %i, key: %@, value: %@", [invoiceDictFromReq count], [invoiceDictFromReq allKeys], [invoiceDictFromReq allValues]); 

// Get values and keys from JSON response 
self.invoiceDict = [invoiceDictFromReq objectForKey:@"invoice"]; 
NSNumber *invoiceAmount = [self.invoiceDict objectForKey:@"amount"]; 
NSNumber *invoiceId = [self.invoiceDict objectForKey:@"id"]; 
NSNumber *invoiceNumber = [self.invoiceDict objectForKey:@"number"]; 
NSNumber *checkoutStarted = [self.invoiceDict objectForKey:@"checkoutStarted"]; 
NSNumber *checkoutCompleted = [self.invoiceDict objectForKey:@"checkoutCompleted"]; 
NSLog(@"amount: %@, id: %@, number: %@, started: %@, completed: %@", invoiceAmount, invoiceId, invoiceNumber, checkoutStarted, checkoutCompleted); 

所有控制檯日誌表明,數據很好。這是事情開始崩潰的地方。 我通過invoiceDict屬性到下一個視圖控制器:

// Pass the invoice to checkoutViewController 
[checkoutViewController setInvoiceDict:self.invoiceDict]; 

在CheckoutViewController.m:

// Change invoice checkoutCompleted to true 
// [self.invoiceDict removeObjectForKey:@"checkoutCompleted"]; 
    [self.invoiceDict setObject:[NSNumber numberWithBool:YES] forKey:@"checkoutCompleted"]; 

的錯誤是在[self.invoiceDict setObject...]。我確信我使用的所有字典都是NSMutableDictionary。我在代碼中留下了一些註釋過的行,以顯示我嘗試過的東西,並且撞到了一堵磚牆。我想我總是可以創建一個新的字典。這是做這件事的首選方法嗎?

回答

9

您正在invoiceDictFromReq中分配一個字典,接下來您要創建另一個字典,您正在創建一個內存泄漏。 刪除線

NSMutableDictionary *invoiceDictFromReq = [[NSMutableDictionary alloc] init]; 

但你的問題是,你正在創建一個的NSMutableDictionary,但你已經設置了self.invoiceDict您mutableDictionary內的字典,這不一定是mutableDictionary了。 改變默認的行

self.invoiceDict = [invoiceDictFromReq objectForKey:@"invoice"]; 

self.invoiceDict = [NSMutableDictionary dictionaryWithDictionary:[invoiceDictFromReq objectForKey:@"invoice"]]; 
+0

感謝您的建議,但它仍然給我同樣的錯誤。現在,我將invoiceDictFromReq作爲.h中的一個屬性並在.m中同步化,並將其設置爲來自json請求的數據,作爲self.invoiceDictFromReq = [NSMutableDictionary dictionary ...] – okysabeni

+1

對不起,我改變了我的答案,那不是。看看你是否仍然有問題。您不必保留invoiceDictFromReq,因爲它是一個本地變量,但首次刪除您創建invoiceDictFromReq的那一行,因爲您有泄漏 –

+0

:-)。當我看到「但你的問題是你正在創建一個NSMutableDictionary,但你正在設置self.invoiceDict一個字典在你的mutableDictionary中,這不一定是一個mutableDictionary」我知道你當場擊中它。對我來說太愚蠢了。感謝您指出。我不應該認爲本地json解析器返回NSMutableDictionary。非常感謝! – okysabeni

15

NSJSONSerialization回報不可變對象。這裏是如何得到可變字典從解析器:

  • 使用選項NSJSONReadingMutableContainers

  • 使用mutableCopy的結果
+1

正是我在找的東西。謝謝!!! – denikov

+0

您不需要使用mutableCopy,只需使用結果即可。NSJSONReadingMutableContainers不僅使結果中的數組和字典變爲可變的,而且也使結果本身。 – gnasher729

相關問題