Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSMutableDictionary: mutating method sent to immutable object

The following code is returning an exception with the following error message "mutating method sent to immutable object" when attempting to removeObjectForKey

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;

Not sure what the issue is, perhaps it is due to retrieving the dictionary from a NSUserDefaults.

However the following code works without any issues.

NSMutableDictionary * storedIpDictionary = (NSMutableDictionary*)[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"dictDeviceIp"];
[storedIpDictionary removeAllObjects];
like image 977
Remixed123 Avatar asked Aug 04 '14 19:08

Remixed123


5 Answers

NSUserDefaults returns immutable objects, even if you put in mutable ones. You must call -mutableCopy on the returned value to get a mutable collection.

like image 59
Catfish_Man Avatar answered Nov 17 '22 22:11

Catfish_Man


You cant just cast an NSDictionary to NSMutableDictinary thats not at all how casting works.

to remove a key from NSUserDefualts call removeObjectForKey on the NSUserDefaults instance itself.

if you really do want a dictionary for some other reason, then you must make a mutableCopy from the dictionary obtained by dictionaryForKey.

like image 32
Brad Allred Avatar answered Nov 17 '22 22:11

Brad Allred


This is the code that eventually worked, I used some of the details provided from others above, but none had it completely explained.

- (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];
}
like image 3
Remixed123 Avatar answered Nov 17 '22 22:11

Remixed123


if you have on error NSMutableDictionary: mutating method sent to immutable object in Swift, make this step:

This is because you have assigned a NSUserDefault to NSMutableArray, when you take something NSUserDefault it returns you a NSArray not a NSMutableArray, so in this case you have to use a NSMutableArray Auxiliary .

see for 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)
}

This work for me!!!

like image 3
Pablo Ruan Avatar answered Nov 17 '22 23:11

Pablo Ruan


i found same issue and found solution hope it will help some one.

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

NSUserDefaults returns immutable objects, even if you put in mutable ones. You must call -mutableCopy on the returned value to get a mutable collection. so when you get value from NSUserDefault use mutableCopy()

like image 3
AyAz Avatar answered Nov 17 '22 22:11

AyAz