NSUserDefaults 保存两个数组导致崩溃
NSUserDefaults save two arrays leading to crash
最近在研究NSUserDefaults
,做了一个demo如下:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *activity_array = [NSMutableArray array];
NSMutableArray *movie_array = [NSMutableArray array];
[defaults setObject:activity_array forKey:@"activity"];
[defaults setObject:movie_array forKey:@"movie"];
[defaults synchronize];
然后我尝试编写以下内容,在此 post 期间我将调用 "code2":
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
NSMutableArray *array = [userDefault objectForKey:@"activity"];
[array addObject:@"123"];
该演示仍然有效。
但是,当我用以下代码替换 "code2" 时,演示崩溃了:
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
NSMutableArray *array = [userDefault objectForKey:@"movie"];
[array addObject:@"123"];
如您所见,区别是关键。
为什么会崩溃?
从 NSUserDefaults 返回的数组和字典总是不可变的,即使你设置的是可变的。你必须调用 -mutableCopy.
NSUserDefaults
可以存储NSMutableArrays
,但会将它们变成不可变数组。
NSDictionary
和 NSMutableDictionary
也是如此。
这意味着如果你想将一个对象添加到你刚刚从 NSUserDefaults
中提取的数组中,你必须首先使其可变,例如使用 -mutableCopy
,或者 -initWithArray
.
NSArray *array = [userDefault objectForKey:@"movie"];
//This works
NSMutableArray *arr = [NSMutableArray alloc]initWithArray:array];
//This works too and is more commonly used.
NSMutableArray *arr = [array mutableCopy];
您现在可以毫不费力地修改数组 arr
,并且您可以像以前一样保存它。如果您之后检索它,它将是修改后的数组。但是要小心,arrays
和 dictionaries
从 NSUserDefaults
中获取时总是不可变的。每次要从 NSUserDefaults
.
修改数组或字典时,都必须这样做 "trick"
编辑:在测试你的代码之后,我唯一的假设是你的无崩溃数组在你检索它时只是 nil 。使用断点调试来验证这一点,但我接近 101% 确定。
EDIT2:特洛伊木马比我更快!
试试这个:
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
NSMutableArray *array = [[userDefault objectForKey:@"movie"]mutableCopy];
正如其他人指出的那样,您从 NSUserDefaults
返回的数组是不可变的,因此在对它们调用 addObject:
时会抛出异常,但是如果数组是 nil
,因为对 nil
对象的调用方法(发送消息)被静默忽略。
因此我相信您的 code2 可以正常工作,因为对象 @"activity"
在用户默认值中不存在,而 @"movie"
存在。
userDefault 中的对象不可变。试试这个
NSMutableArray *arr = (NSMutableArray *)[userDefault objectForKey:@"activity"];
或者如果您喜欢使用 id 并首先检查其 class 以防止崩溃:
id variableName = [userDefault objectForKey:@"activity"];
if ([[variableName class] isEqual:[NSArray class]])
{
NSMutableArray *arr = [[NSMutableArray alloc] initWithArray:(NSArray *)variableName];
NSMutableArray *arr = [(NSArray *)variableName mutableCopy];
}
else if ([[variableName class] isEqual:[NSNull class]])
NSLog(@"no object with key:activity");
else
NSLog(@"not array");
//Happy coding.. :)
最近在研究NSUserDefaults
,做了一个demo如下:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *activity_array = [NSMutableArray array];
NSMutableArray *movie_array = [NSMutableArray array];
[defaults setObject:activity_array forKey:@"activity"];
[defaults setObject:movie_array forKey:@"movie"];
[defaults synchronize];
然后我尝试编写以下内容,在此 post 期间我将调用 "code2":
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
NSMutableArray *array = [userDefault objectForKey:@"activity"];
[array addObject:@"123"];
该演示仍然有效。
但是,当我用以下代码替换 "code2" 时,演示崩溃了:
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
NSMutableArray *array = [userDefault objectForKey:@"movie"];
[array addObject:@"123"];
如您所见,区别是关键。
为什么会崩溃?
从 NSUserDefaults 返回的数组和字典总是不可变的,即使你设置的是可变的。你必须调用 -mutableCopy.
NSUserDefaults
可以存储NSMutableArrays
,但会将它们变成不可变数组。
NSDictionary
和 NSMutableDictionary
也是如此。
这意味着如果你想将一个对象添加到你刚刚从 NSUserDefaults
中提取的数组中,你必须首先使其可变,例如使用 -mutableCopy
,或者 -initWithArray
.
NSArray *array = [userDefault objectForKey:@"movie"];
//This works
NSMutableArray *arr = [NSMutableArray alloc]initWithArray:array];
//This works too and is more commonly used.
NSMutableArray *arr = [array mutableCopy];
您现在可以毫不费力地修改数组 arr
,并且您可以像以前一样保存它。如果您之后检索它,它将是修改后的数组。但是要小心,arrays
和 dictionaries
从 NSUserDefaults
中获取时总是不可变的。每次要从 NSUserDefaults
.
编辑:在测试你的代码之后,我唯一的假设是你的无崩溃数组在你检索它时只是 nil 。使用断点调试来验证这一点,但我接近 101% 确定。
EDIT2:特洛伊木马比我更快!
试试这个:
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
NSMutableArray *array = [[userDefault objectForKey:@"movie"]mutableCopy];
正如其他人指出的那样,您从 NSUserDefaults
返回的数组是不可变的,因此在对它们调用 addObject:
时会抛出异常,但是如果数组是 nil
,因为对 nil
对象的调用方法(发送消息)被静默忽略。
因此我相信您的 code2 可以正常工作,因为对象 @"activity"
在用户默认值中不存在,而 @"movie"
存在。
userDefault 中的对象不可变。试试这个
NSMutableArray *arr = (NSMutableArray *)[userDefault objectForKey:@"activity"];
或者如果您喜欢使用 id 并首先检查其 class 以防止崩溃:
id variableName = [userDefault objectForKey:@"activity"];
if ([[variableName class] isEqual:[NSArray class]])
{
NSMutableArray *arr = [[NSMutableArray alloc] initWithArray:(NSArray *)variableName];
NSMutableArray *arr = [(NSArray *)variableName mutableCopy];
}
else if ([[variableName class] isEqual:[NSNull class]])
NSLog(@"no object with key:activity");
else
NSLog(@"not array");
//Happy coding.. :)