NSKeyedUnarchiver unarchiveObjectWithFile:在init:方法中返回nil

时间:2009-08-29 18:02:41

标签: iphone cocoa-touch

更新:如果我从applicationDidFinishLaunching:调用archiveRootObject:如果我从单例类的init:方法调用它,它将返回nil。

我对NSKeyedUnarchiver unarchiveObjectWithFile的行为非常困惑。 The documentation表示如果文件不存在,它将返回nil。使用我的一个对象,会发生以下情况:

Game *g1 = [Game getGame];
NSString *archivePath = [Game getArchivePath];
bool success = [NSKeyedArchiver archiveRootObject:g1 toFile:archivePath];
Game *g2 = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];

// success is true, g2 is nil

我已经验证该文件确实存在并且正由archiveRootObject:方法写入。我做错了什么阻止我将游戏对象从存档中取回?

2 个答案:

答案 0 :(得分:8)

我在使用ARC支持的Xcode 4.1中遇到了同样的问题:

BOOL isFileExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
NSAssert(isFileExist, @"filePath does not exist");
NSKeyedUnarchiver* coder =
    [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; // nil
NSData* data = [[NSFileManager defaultManager] contentsAtPath:filePath];
coder = [NSKeyedUnarchiver unarchiveObjectWithData:data]; // nil
coder = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; // OK!!!

这似乎是可可触摸中的一个错误。

修改

它的行为与此类似,并非错误。但我同意命名很容易导致错误。

[[NSKeyedUnarchiver alloc] initForReadingWithData:]会返回NSKeyedUnarchiver个实例。

[NSKeyedUnarchiver unarchiveObjectWithData:]返回根对象。这是一种方便的方法:

NSKeyedUnarchiver *coder = [[self alloc] initForReadingWithData:arg2];
id object = [coder decodeObjectForKey:@"root"];

答案 1 :(得分:2)

  1. 您必须始终-retain未归档的对象:Game *g2 = [[NSKeyedUnarchiver unarchiveObjectWithFile:archivePath] retain];

  2. 您的g2是否符合NSCoding?如果它没有在<NSCoding>标题中声明g2,请确保它确实如此。在实现文件中定义方法-(id)initWithCoder:(NSCoder *)coder-(void)encodeWithCoder:(NSCoder *)coder

  3. 如果您正在努力使其工作,请考虑归档和取消归档标准NSObject,如NSString或其他类似的。您可能不需要存档整个自定义对象,可能只是剩余的时间编号,游戏位置或位置或分数。换句话说,归档和取消归档所需的最低限度。