将对象添加到从 NSUserDefaults 加载的 NSMutableDictionary 中的数组
Add object to array within NSMutableDictionary loaded from NSUserDefaults
我在 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'
您可以直接将对象添加到数组中:
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]];
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]]]
以下是 the documentation for dictionaryForKey:
在 NSUserDefaults 上的说法:
Special Considerations
The returned dictionary and its contents are immutable, even if the values you >originally set were mutable.
因此,当您从 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.
我在 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'
您可以直接将对象添加到数组中:
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]];
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]]]
以下是 the documentation for dictionaryForKey:
在 NSUserDefaults 上的说法:
Special Considerations
The returned dictionary and its contents are immutable, even if the values you >originally set were mutable.
因此,当您从 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.