NSKeyedUnarchiver unarchiveObjectWithFile: returns nil in init: method

匿名 (未验证) 提交于 2019-12-03 02:24:01

问题:

Update: This works if I call archiveRootObject: from applicationDidFinishLaunching:. If I call it from the init: method of a singleton class, it returns nil.

I'm very confused by the behavior of NSKeyedUnarchiver unarchiveObjectWithFile:. The documentation says that it will return nil if the file doesn't exist. With one of my objects, the following happens:

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 

I've verified that the file actually does exist and is getting written to by the archiveRootObject: method. What am I doing wrong preventing me from getting a Game object back out of the archive?

回答1:

I've meet the same trouble in Xcode 4.1 with ARC support:

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!!! 

It seems to be a bug in cocoa-touch.

Edit:

It is intended to behave like this and is not a bug. But I agree that the naming easily leads to mistakes.

[[NSKeyedUnarchiver alloc] initForReadingWithData:] returns a NSKeyedUnarchiver instance.

[NSKeyedUnarchiver unarchiveObjectWithData:] returns the root object. It is a conviencen method for:

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


回答2:

  1. You must always -retain an unarchived object: Game *g2 = [[NSKeyedUnarchiver unarchiveObjectWithFile:archivePath] retain];

  2. Does your g2 conform to NSCoding? Make sure it does, if it doesn't declare <NSCoding> in the g2 header. In the implementation file define methods -(id)initWithCoder:(NSCoder *)coder and -(void)encodeWithCoder:(NSCoder *)coder

  3. If you're struggling to get this to work consider archiving and unarchiving a standard NSObject, like an NSString or some such. You probably don't need to archive a whole custom object, maybe just a remaining time number, game location or position or score. In other words, archive and unarchive the bare minimum you need.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!