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?
You must always
-retain
an unarchived object:Game *g2 = [[NSKeyedUnarchiver unarchiveObjectWithFile:archivePath] retain];
Does your
g2
conform toNSCoding
? Make sure it does, if it doesn't declare<NSCoding>
in theg2
header. In the implementation file define methods-(id)initWithCoder:(NSCoder *)coder
and-(void)encodeWithCoder:(NSCoder *)coder
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.
I've meet the same trouble in Xcode 4.1 with ARC support:
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 aNSKeyedUnarchiver
instance.[NSKeyedUnarchiver unarchiveObjectWithData:]
returns the root object. It is a conviencen method for: