NSMutableDictionary: метод мутирования, отправленный на неизменяемый объект

Следующий код возвращает исключение со следующим сообщением об ошибке "Метод мутирования, отправленный на неизменяемый объект" при попытке удалить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];

Ответы

Ответ 1

Это код, который в конечном итоге сработал, я использовал некоторые детали, предоставленные другими выше, но ни один из них не был полностью объяснен.

- (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 saved
    [[NSUserDefaults standardUserDefaults] synchronize];
}

Ответ 2

NSUserDefaults возвращает неизменяемые объекты, даже если вы введете изменчивые. Вы должны вызвать -mutableCopy для возвращаемого значения, чтобы получить измененную коллекцию.

Ответ 3

Вы не можете просто отличить NSDictionary до NSMutableDictinary отнюдь не о том, как работает кастинг.

удалить ключ из NSUserDefualts вызова removeObjectForKey в самом экземпляре NSUserDefaults.

Если вам действительно нужен словарь по какой-то другой причине, тогда вы должны сделать mutableCopy из словаря, полученного с помощью dictionaryForKey.

Ответ 4

если у вас есть ошибка NSMutableDictionary: метод мутирования, отправленный в неизменяемый объект в Swift, выполните этот шаг:

Это связано с тем, что вы назначили NSUserDefault для NSMutableArray, когда вы берете что-то 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)
}

Эта работа для меня!!!

Ответ 5

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

Ответ 6

Я нашел ту же проблему и нашел решение, надеюсь, что это поможет кому-то.

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

NSUserDefaults возвращает неизменяемые объекты, даже если вы введете изменчивые. Вы должны вызвать -mutableCopy для возвращаемого значения, чтобы получить изменчивую коллекцию. поэтому, когда вы получаете значение из NSUserDefault, используйте mutableCopy()