NSMutableDictionary:发送到不可变对象的变异方法

NSMutableDictionary: mutating method sent to immutable object

提问人:Remixed123 提问时间:8/5/2014 更新时间:6/20/2016 访问量:18642

问:

以下代码返回异常,并显示以下错误消息“mutating method sent to immutable object”时尝试删除 ObjectForKey

NSMutableDictionary * storedIpDictionary = (NSMutableDictionary*)[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"dictDeviceIp"];

NSString *key = self.currentDeviceNameText.text;
NSString *ipAddressTemp = [storedIpDictionary objectForKey:key];

[storedIpDictionary removeObjectForKey:key]; <----Crashes here

storedIpDictionary[key] = ipAddressTemp;

不确定问题是什么,可能是由于从 NSUserDefaults 检索字典。

但是,以下代码可以正常工作,没有任何问题。

NSMutableDictionary * storedIpDictionary = (NSMutableDictionary*)[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"dictDeviceIp"];
[storedIpDictionary removeAllObjects];
iOS的 目标-C nsuserdefaults nsmutable词典 可变

评论

1赞 Hot Licks 8/5/2014
消息说了什么?你认为这意味着什么?什么是不可变对象?将 NSDictionary 强制转换为 NSMutableDictionary 指针是否使字典可变?
0赞 Remixed123 8/5/2014
我不确定为什么它是 NSDictionary,因为 NSUserDefault 被定义为 NSMutableDictionary - @property(非原子,保留)NSMutableDictionary* dictDeviceIp;
0赞 Bob Arezina 11/25/2014
不知道为什么这个问题被否决了,这解决了我的问题。
0赞 Remixed123 3/1/2015
谢谢鲍勃,人们在反对票上太快了,通常是在阅读整个问题之前就完成了。无论如何,很高兴看到这篇文章又回来了!尽管有那么多反对票,这意味着很多人都得到了帮助。

答:

3赞 Brad Allred 8/5/2014 #1

你不能只是投射一个根本不是铸造工作原理。NSDictionaryNSMutableDictinary

从实例本身的调用中删除密钥。NSUserDefualtsremoveObjectForKeyNSUserDefaults

如果你真的出于其他原因想要一个字典,那么你必须从 获得的字典中制作一个。mutableCopydictionaryForKey

56赞 Catfish_Man 8/5/2014 #2

NSUserDefaults 返回不可变对象,即使放入可变对象也是如此。您必须对返回的值调用 -mutableCopy 才能获取可变集合。

2赞 Droppy 8/5/2014 #3

[NSUserDefaults dictionaryForKey]返回一个不可变的字典 (),并且不能通过将其强制转换为 来强制它可变。NSDictionaryNSMutableDictionary

相反,您必须使用 创建可变字典 ,覆盖该元素,然后将字典重新分配回:mutableCopyNSUserDefaults

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *storedIpDictionary = [[userDefaults dictionaryForKey:@"dictDeviceIp"] mutableCopy];

NSString *key = self.currentDeviceNameText.text;
NSString *ipAddressTemp = [storedIpDictionary objectForKey:key];

// Don't need this line
//[storedIpDictionary removeObjectForKey:key];

storedIpDictionary[key] = ipAddressTemp;
[userDefaults setObject:storedIpDictionary
                 forKey:@"dictDeviceIp"];
3赞 Remixed123 8/5/2014 #4

这是最终起作用的代码,我使用了上面其他人提供的一些细节,但没有一个完全解释。

- (void)cleanDictionary
{
    NSMutableDictionary * storedIpDictionary = [[[NSUserDefaults standardUserDefaults] objectForKey: @"dictDeviceIp"] mutableCopy];

    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"dictDeviceIp"];

    NSString *oldKey = self.currentDeviceNameText.text;
    NSString *newKey = self.deviceNameChangeText.text;
    NSString *ipAddressTemp = [storedIpDictionary objectForKey:oldKey];

    // Make some change to the structure
    [storedIpDictionary removeObjectForKey:oldKey];  // Remove object
    storedIpDictionary[newKey] = ipAddressTemp;      // Add object with new key

    // Add it the whole thing back into NSUserDefaults
    [[NSUserDefaults standardUserDefaults] setObject:storedIpDictionary forKey:@"dictDeviceIp"];

    // Synchronize to ensure it's saved
    [[NSUserDefaults standardUserDefaults] synchronize];
}
3赞 Pablo Ruan 10/30/2015 #5

如果您在 Swift 中遇到错误 NSMutableDictionary: mutating method sent to immutable object,请执行以下步骤:

这是因为您已将 NSUserDefault 分配给 NSMutableArray,当您获取某些 NSUserDefault 时,它会返回 NSArray 而不是 NSMutableArray,因此在这种情况下,您必须使用 NSMutableArray Auxiliary 。

请参阅 Swift:

var Products:NSMutableArray = NSMutableArray()


override func viewDidAppear(animated: Bool) {

    if let Produtos = NSUserDefaults.standardUserDefaults().valueForKey("Produtos") {
        Products = Produtos as! NSMutableArray
    }
}

func InsertProducts(productCode:String){
     //COPY Products Atual for auxMutable
     var auxMutable = Products.mutableCopy()

        //Add object in auxMutable
        auxMutable.addObjectsFromArray([productCode])

        //in line back data to Array Products and make cast to NSMutableArray
        Products = auxMutable as! NSMutableArray

        //Refresh Data of NSUserDefaults
        NSUserDefaults.standardUserDefaults().setObject(Products, forKey: "Produtos")
}


@IBAction func Bt_New_Product(sender: AnyObject) {
     var ProductName:String = TXT_NameProduct.text

     InsertProducts(ProductName)
}

这对我有用!!

3赞 AyAz 6/20/2016 #6

我发现了同样的问题并找到了解决方案,希望它能帮助一些人。

arrayOfferId = defaults.objectForKey("offerId")?.mutableCopy() as! NSMutableArray

NSUserDefaults 返回不可变对象,即使放入可变对象也是如此。您必须对返回的值调用 -mutableCopy 才能获取可变集合。因此,当您从 NSUserDefault 获取值时,请使用 mutableCopy()