我想存储一个UIImage数组,我这样做:
//in didFinishLaunchingWithOption
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:@"theKey"];
if (data == NULL) arrayImage = [[NSMutableArray alloc] init];
else {arrayImage = [[NSMutableArray alloc] init]; arrayImage = [NSKeyedUnarchiver unarchiveObjectWithData:data];}
NSLog(@"arrayImage:%@", arrayImage);
//and in applicationDidEnterBackground
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arrayImage];
[defaults setObject:data forKey:@"theKey"];
NSLog(@"arrayImage:%@", arrayImage);
当app在nslog中的didFinishLaunchingWithOption中运行时,我看到我的数组中的所有对象,但是当我使用它时,我发生了一个崩溃,说“[__NSArrayM count]:消息发送到解除分配的实例”为什么?
答案 0 :(得分:1)
我假设您没有使用ARC。问题在于:
if (data == NULL)
arrayImage = [[NSMutableArray alloc] init];
else {
arrayImage = [[NSMutableArray alloc] init];
// HERE
arrayImage = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
在HERE
,您将arrayImage
中的值替换为keyed unarchiver的新实例。您之前init
'的值会丢失(事实上已泄露)。 unarchiver中的值是一个自动释放的对象,因此将在池耗尽时释放。这是在applicationDidEnterBackground
来电之前。
正确的解决方案是保留unarchiver的值。即:
if (data == nil)
arrayImage = [[NSMutableArray alloc] init];
else
arrayImage = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain];
答案 1 :(得分:1)
我不完全确定,但我认为
+(id)unarchiveObjectWithData:(NSData *)data
为您提供一个自动释放的对象,因此您可以保留它。而且我认为它会给你一个不可变的对象,所以当你试图添加或删除它的对象时你会得到一个错误(我不确定这个,但我想我曾经在这种情况下.. 。)
我会重写你代码的一部分:
...
if (data == nil)
{
arrayImage = [[NSMutableArray alloc] init];
} else
{
//arrayImage = [[NSMutableArray alloc] init]; //why to allocate and initialize if you are goind to unarchive it?
//arrayImage = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain]; //note the retain here
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data]; //the unarchive won't mantain mutability (I guess).
arrayImage = [NSMutableArray arrayWithArray:arr]; //create a mutable copy
}
...