更新:如果我从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:方法写入。我做错了什么阻止我将游戏对象从存档中取回?
答案 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)
您必须始终-retain
未归档的对象:Game *g2 = [[NSKeyedUnarchiver unarchiveObjectWithFile:archivePath] retain];
您的g2
是否符合NSCoding
?如果它没有在<NSCoding>
标题中声明g2
,请确保它确实如此。在实现文件中定义方法-(id)initWithCoder:(NSCoder *)coder
和-(void)encodeWithCoder:(NSCoder *)coder
如果您正在努力使其工作,请考虑归档和取消归档标准NSObject,如NSString或其他类似的。您可能不需要存档整个自定义对象,可能只是剩余的时间编号,游戏位置或位置或分数。换句话说,归档和取消归档所需的最低限度。