【问题标题】:Add object to array within NSMutableDictionary loaded from NSUserDefaults将对象添加到从 NSUserDefaults 加载的 NSMutableDictionary 中的数组
【发布时间】:2015-07-11 10:17:06
【问题描述】:

我在 NSMutableDictionary 中有一个数组,我想向其中添加对象。使用我目前的方法,我得到一个错误,说数组是不可变的。

我认为问题出在我将字典保存到 NSUserDefaults 时。我正在检索它是 NSDictionary,但同时我正在创建一个新的 NSMutableDictionary 内容。

但是,数组似乎是不可变的。如何替换字典中的数组?

我的字典是这样的:

NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], nil];

NSDictionary *dict = @{

                     @"firstKey": @{
                                     @"theArray":array,
                                   }

                      };

NSMutableDictionary *mutDict = [[NSMutableDictionary alloc] initWithDictionary:dict];

我正在尝试添加这样的对象:

[[[mutDict objectForKey:@"firstKey"] objectForKey:@"theArray"] addObject:[NSNumber numberWithInt:5]];

我可以在将对象保存到NSUserDefaults之前将对象添加到mutDict内的数组中

从 NSUserDefaults 加载字典后尝试添加到字典中的数组时收到的错误消息:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'

【问题讨论】:

  • 这里有两个字典。键“theArray”来自第二个字典。您想向第二个字典添加更多键/值,对吗?
  • 我想在“数组”中添加更多值,即向键 @“theArray”的值添加更多对象。我说得通吗?
  • 好的,通过这种方式,您可以替换具有键“theArray”的整个数组。例如。使用数组初始化可变数组(您的“theArray”)添加项目并将值设置为字典键“theArray”
  • 好的,你能给我一个可以替换数组的例子吗?我需要删除旧的然后添加新的吗?非常感谢。
  • 您的代码运行良好,它向数组2015-07-11 11:40:05.599 TestC[422:4891] { firstKey = { theArray = ( 0, 5 ); }; }添加了一个新数字5

标签: ios objective-c nsarray nsdictionary nsuserdefaults


【解决方案1】:

这是the documentation for dictionaryForKey: 在 NSUserDefaults 上所说的:

特殊注意事项

返回的字典及其内容是不可变的,即使您>最初设置的值是可变的。

因此,当您从 NSUserDefaults 检索字典时,字典本身以及其中的所有集合都是不可变的。您可以使顶级字典可变(我假设您正在这样做),但这不会传播到现在不可变的 NSArrays 中,它们是字典中的值。

解决这个问题的唯一方法是检查返回的字典,并将不可变的 NSArray 替换为可变的对应物。它可能看起来像这样。

- (NSMutableDictionary *)deepMutableCopyOfDictionary:(NSDictionary *)dictionary
{
    NSMutableDictionary *mutableDictionary = [dictionary mutableCopy];
    for (id key in [mutableDictionary allKeys]) {
        id value = mutableDictionary[key];
        if ([value isKindOfClass:[NSDictionary class]]) {
            // If the value is a dictionary make it mutable and call recursively
            mutableDictionary[key] = [self deepMutableCopyOfDictionary:dictionary[key]];
        }
        else if ([value isKindOfClass:[NSArray class]]) {
            // If the value is an array, make it mutable
            mutableDictionary[key] = [(NSArray *)value mutableCopy];
        }
    }
    return mutableDictionary;
}

说实话,虽然听起来您正在使用 NSUserDefaults 来完成比预期复杂得多的事情。如果你想持久化复杂的数据结构,那么你应该研究 Core Data 之类的东西,或者如果这看起来有点矫枉过正,请看一下 NSKeyedArchiver

【讨论】:

  • 很好的答案,正是我想要的。谢谢!将考虑为此用例替换 NSUserDefaults。
【解决方案2】:

您可以直接将对象添加到数组中:

NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], nil];

NSDictionary *dict = @{

                     @"firstKey": @{
                                     @"theArray":array,
                                   }

                      };

NSMutableDictionary *mutDict = [[NSMutableDictionary alloc] initWithDictionary:dict];

//Since Objective-C objects are always passed by reference (using pointers) you can add object to the array
[array addObject:[NSNumber numberWithInt:55]];

【讨论】:

    【解决方案3】:

    将对象添加到作为字典一部分的数组的 Swift 示例。

    let arr = [0] // note that initial array may be immutable
    
    var dict = ["fK": ["a":arr]] // even if "arr" will be mutable, but "dict" immutable
    
    dict["fK"]!["a"]!.append(3) // this will not work. "dict" must be mutable
    
    println(dict) //[fK: [a: [0, 3]]]
    

    另一种方法

    var arr = [0] // initial array must be mutable
    
    var dict = ["fK": ["a":arr]] // in both cases dictionary must be mutable 
    
    arr.append(3)
    
    let newArr = arr
    
    dict["fK"]!["a"]! = newArr // because we change it's content
    
    println(dict) //[fK: [a: [0, 3]]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多