尽管对象是 NSMutableDictionary,但“发送到不可变对象的变异方法”
Posted
技术标签:
【中文标题】尽管对象是 NSMutableDictionary,但“发送到不可变对象的变异方法”【英文标题】:"Mutating method sent to immutable object" despite object being NSMutableDictionary 【发布时间】:2011-11-28 16:32:14 【问题描述】:我正在使用 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
。我在代码中留下了一些注释掉的行来显示我尝试过的东西,但我碰了壁。我想我总是可以创建一个新字典。这是首选的方法吗?
【问题讨论】:
【参考方案1】:NSJSONSerialization
默认返回不可变对象。以下是如何从解析器中获取可变字典:
NSJSONReadingMutableContainers
或
在结果上使用mutableCopy
【讨论】:
不需要使用mutableCopy,使用结果即可。 NSJSONReadingMutableContainers 不仅使结果中的数组和字典可变,还使结果本身可变。【参考方案2】:您在 invoiceDictFromReq 中分配一个字典,接下来您将创建另一个字典,您将在那里创建内存泄漏。 删除该行
NSMutableDictionary *invoiceDictFromReq = [[NSMutableDictionary alloc] init];
但是您的问题是您正在创建一个 NSMutableDictionary,但您正在将 mutableDictionary 中的字典设置为 self.invoiceDict,这也不一定是 mutableDictionary。 换行
self.invoiceDict = [invoiceDictFromReq objectForKey:@"invoice"];
为
self.invoiceDict = [NSMutableDictionary dictionaryWithDictionary:[invoiceDictFromReq objectForKey:@"invoice"]];
【讨论】:
感谢您的建议,但它仍然给我同样的错误。现在,我将 invoiceDictFromReq 作为 .h 中的属性并在 .m 中合成,并将其设置为来自 json 请求的数据 self.invoiceDictFromReq = [NSMutableDictionary dictionary...] 对不起,我改变了答案,不是那样。看看你是否还有问题。您不必保留 invoiceDictFromReq 因为它是一个局部变量,但删除您第一次创建 invoiceDictFromReq 的行,因为那里有泄漏 :-)。当我看到,“但是你的问题是你正在创建一个 NSMutableDictionary 但你正在设置 self.invoiceDict 一个字典在你的 mutableDictionary 中,那也不一定是 mutableDictionary”我知道你当场就成功了。我太傻了。感谢您指出。我不应该假设本机 json 解析器返回 NSMutableDictionary。非常感谢!以上是关于尽管对象是 NSMutableDictionary,但“发送到不可变对象的变异方法”的主要内容,如果未能解决你的问题,请参考以下文章
试图在 NSMutableDictionary 中设置 Number 类型的对象并得到奇怪的警告
使用 NSMutableDictionary 将对象保存到数组