NSKeyedUnarchiver unarchiveObjectWithFile: returns nil in the init: method

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

I am very confused by the behavior of NSKeyedUnarchiver unarchiveObjectWithFile :. The documentation says that it will return zero if the file does not 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 checked that the file really exists and is being written with the archiveRootObject: method. What am I doing wrong, not allowing me to return the game object from the archive?

+7
iphone cocoa-touch
source share
2 answers

I encounter the same issue 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!!! 

This seems to be a bug in cocoa -touch.

Edit:

It is supposed to behave like this, and this is not a mistake. But I agree that naming easily leads to errors.

[[NSKeyedUnarchiver alloc] initForReadingWithData:] returns an instance of NSKeyedUnarchiver .

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

 NSKeyedUnarchiver *coder = [[self alloc] initForReadingWithData:arg2]; id object = [coder decodeObjectForKey:@"root"]; 
+7
source share
  • You should always -retain unarchived object: Game *g2 = [[NSKeyedUnarchiver unarchiveObjectWithFile:archivePath] retain];

  • Does your g2 NSCoding ? Make sure he does this if he does not declare <NSCoding> in the g2 header. In the implementation file, define the methods -(id)initWithCoder:(NSCoder *)coder and -(void)encodeWithCoder:(NSCoder *)coder

  • If you are trying to get this to work, consider archiving and unlocking a standard NSObject, such as NSString or some of them. You probably don't need to archive the whole user object, maybe just the remaining time number, game location or position or rating. In other words, archive and unzip the minimum minimum you need.

+2
source share

All Articles