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

时间:2014-08-04 19:30:54

标签: ios objective-c nsuserdefaults nsmutabledictionary mutable

以下代码在尝试removeObjectForKey时返回一个异常,并显示以下错误消息“mutating method sent to immutable object”

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];

6 个答案:

答案 0 :(得分:55)

NSUserDefaults返回不可变对象,即使你输入了可变对象。您必须对返回的值调用-mutableCopy以获取可变集合。

答案 1 :(得分:3)

你不能仅仅将NSDictionary投射到NSMutableDictinary,而不是投射的方式。

NSUserDefualts实例本身的removeObjectForKey电话NSUserDefaults移除密钥。

如果您确实因某些其他原因需要字典,那么您必须从mutableCopy获得的字典中创建dictionaryForKey

答案 2 :(得分:3)

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

- (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 :(得分:3)

如果您有错误NSMutableDictionary:在Swift中发送到不可变对象的mutating方法,请执行以下步骤:

这是因为你已经为NSMutableArray分配了一个NSUserDefault,当你拿NSUserDefault时它会返回一个NSArray而不是NSMutableArray,所以在这种情况下你必须使用NSMutableArray辅助。

参见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)
}

这项工作对我来说!!!

答案 4 :(得分:3)

我发现了同样的问题,发现解决方案希望它能帮到某个人。

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

NSUserDefaults返回不可变对象,即使你输入了可变对象。您必须在返回的值上调用-mutableCopy以获取可变集合。所以当你从NSUserDefault获得价值时,请使用mutableCopy()

答案 5 :(得分:2)

[NSUserDefaults dictionaryForKey]返回一个不可变的字典(NSDictionary),你不能通过将它强制转换为NSMutableDictionary来强制它变异。

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

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"];
相关问题