IOS:NSUserDefault用于UIImage数组

时间:2012-01-26 12:37:03

标签: ios xcode nsuserdefaults nskeyedarchiver

我想存储一个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]:消息发送到解除分配的实例”为什么?

2 个答案:

答案 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
}
...