"Mutating方法发送到不可变对象",尽管对象是NSMutableDictionary

oky*_*eni 7 cocoa-touch objective-c nsdictionary nsmutabledictionary ios

我正在使用NSMutableDictionary并点击此错误:

'NSInternalInconsistencyException', reason: '-[__NSCFDictionary removeObjectForKey:]: mutating method sent to immutable object'
Run Code Online (Sandbox Code Playgroud)

这是代码:

    // 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);
Run Code Online (Sandbox Code Playgroud)

所有控制台日志都表明数据正常.事情开始崩溃的地方.我将invoiceDict属性传递给下一个视图控制器:

// Pass the invoice to checkoutViewController
[checkoutViewController setInvoiceDict:self.invoiceDict];
Run Code Online (Sandbox Code Playgroud)

在CheckoutViewController.m中:

    // Change invoice checkoutCompleted to true
//    [self.invoiceDict removeObjectForKey:@"checkoutCompleted"];
    [self.invoiceDict setObject:[NSNumber numberWithBool:YES] forKey:@"checkoutCompleted"];
Run Code Online (Sandbox Code Playgroud)

错误发生在[self.invoiceDict setObject...].我确保我使用的所有词典都是NSMutableDictionary.我在代码中留下了一些注释掉的行,以显示我尝试过的东西,然后我碰到了一堵砖墙.我想我总能创建一个新词典.这是首选方式吗?

Tri*_*ops 15

NSJSONSerialization默认情况下返回不可变对象.以下是如何从解析器获取可变字典:

  • 使用选项 NSJSONReadingMutableContainers

要么

  • mutableCopy在结果上


Bru*_*ues 9

您正在invoiceDictFromReq中分配字典,然后您正在创建另一个字典,您正在创建内存泄漏.删除该行

NSMutableDictionary *invoiceDictFromReq = [[NSMutableDictionary alloc] init];
Run Code Online (Sandbox Code Playgroud)

但是你的问题是你正在创建一个NSMutableDictionary,但你设置self.invoiceDict你的mutableDictionary里面的一个字典,也不一定是mutableDictionary.改变线

self.invoiceDict = [invoiceDictFromReq objectForKey:@"invoice"];
Run Code Online (Sandbox Code Playgroud)

对于

self.invoiceDict = [NSMutableDictionary dictionaryWithDictionary:[invoiceDictFromReq objectForKey:@"invoice"]];
Run Code Online (Sandbox Code Playgroud)