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

相关问题