web-dev-qa-db-ja.com

NSMutableDictionary:不変オブジェクトに送信される変更メソッド

次のコードは、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;

問題が何であるかわからない、おそらくそれはNSUserDefaultsから辞書を取得することが原因です。

ただし、次のコードは問題なく機能します。

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

これは最終的に機能したコードであり、上記の他の人から提供された詳細の一部を使用しましたが、完全に説明されたものはありませんでした。

- (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
Remixed123

NSUserDefaultsは、可変オブジェクトを配置した場合でも、不変オブジェクトを返します。可変コレクションを取得するには、戻り値に対して-mutableCopyを呼び出す必要があります。

56
Catfish_Man

NSDictionaryNSMutableDictinaryにキャストすることはできませんが、キャストの仕組みはまったく異なります。

NSUserDefualtsからキーを削除するには、removeObjectForKeyインスタンス自体でNSUserDefaultsを呼び出します。

他の理由で本当に辞書が必要な場合は、mutableCopyによって取得された辞書からdictionaryForKeyを作成する必要があります。

3
Brad Allred

私は同じ問題を見つけ、解決策を見つけました。それが誰かを助けることを願っています。

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

NSUserDefaultsは、可変オブジェクトを配置した場合でも、不変オブジェクトを返します。可変コレクションを取得するには、戻り値に対して-mutableCopyを呼び出す必要があります。したがって、NSUserDefaultから値を取得するときは、mutableCopy()を使用します。

3
AyAz

エラーNSMutableDictionary:Swiftの不変オブジェクトに送信された変更メソッドがある場合は、次の手順を実行します。

これは、NSUserDefaultをNSMutableArrayに割り当てたためです。NSUserDefaultを取得すると、NSMutableArrayではなくNSArrayが返されるため、この場合はNSMutableArrayAuxiliaryを使用する必要があります。

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
Pablo Ruan

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