Archiving is supported by archiver objects and the NSCoding
protocol. The protocol consists of two methods: initWithCoder:
and encodeWithCoder:
. There are two forms of archiving, classic and keyed. Both techniques support versioning.
Keyed Archiving
Classic Archiving
Combining Archiving Techniques
Versioning
Using keyed archiving you encode and decode values as key-value pairs, as illustrated in the following example:
- (void)encodeWithCoder:(NSCoder *)encoder |
{ |
[encoder encodeObject:department forKey:@"department"]; |
[encoder encodeObject:lastName forKey:@"Last"]; |
[encoder encodeObject:firstName forKey:@"First"]; |
[encoder encodeInt: employeeID forKey:@"EmpID"]; |
} |
- initWithCoder:(NSCoder *)decoder |
{ |
[self setDepartment:[decoder decodeObjectForKey:@"department"]]; |
employeeID = [decoder decodeIntForKey:@"EmpID"]; |
[self setLastName:[decoder decodeObjectForKey:@"Last"]]; |
[self setFirstName:[decoder decodeObjectForKey:@"First"]]; |
return self; |
} |
The order in which variables are encoded and decoded does not have to match.
If you need to support versions of Mac OS X prior to 10.2, you cannot use keyed archiving. Using classic archiving, you must encode and decode instance variables in the same order, as illustrated in the following example:
- (void)encodeWithCoder:(NSCoder *)encoder |
{ |
[encoder encodeObject:firstName]; |
[encoder encodeObject:lastName]; |
[encoder encodeObject:department]; |
[encoder encodeValueOfObjCType:@encode(int) at:&employeeID]; |
} |
- initWithCoder:(NSCoder *)decoder |
{ |
[self setFirstName:[decoder decodeObject]]; |
[self setLastName:[decoder decodeObject]]; |
[self setDepartment:[decoder decodeObject]]; |
[decoder decodeValueOfObjCType:@encode(int) at:&employeeID]; |
return self; |
} |
Classic archiving is deprecated, so you should migrate your archives to the keyed format. If you need to support classic and keyed archiving, you can combine archiving techniques, as illustrated in the following example:
- (void)encodeWithCoder:(NSCoder *)encoder |
{ |
if ([encoder allowsKeyedCoding]) |
{ |
[encoder encodeObject:firstName forKey:@"First"]; |
[encoder encodeObject:lastName forKey:@"Last"]; |
[encoder encodeInt: employeeID forKey:@"EmpID"]; |
[encoder encodeObject:department forKey:@"department"]; |
} |
else |
{ |
[encoder encodeObject:firstName]; |
[encoder encodeObject:lastName]; |
[encoder encodeObject:department]; |
[encoder encodeValueOfObjCType:@encode(int) at:&employeeID]; |
} |
} |
The corresponding initWithCoder:
method follows a similar pattern.
The archiving mechanism allows version information to be stored in archives. You set a class's version number with the setVersion:
method—typically in the class's initialize
method.
You use the NSCoder
method versionForClassName:
to retrieve the class's version from an archive. If you need to obtain the version from within an NSCoding
protocol or other method, you should use the class name explicitly (for example, version = [MyClass version]
). If you simply send version
to the return value of class
, a subclass's version number may be returned instead.
If you use Core Data for object persistence, then you do not use NSCoder
-based archiving or versioning. On Mac OS X v10.5, Core Data provides an infrastructure for data migration based on versioned managed object models—for more details, see Core Data Model Versioning and Data Migration Programming Guide. (On Mac OS X v10.4, you can add version information to the metadata for a store using the persistent store coordinator method setMetadata:forPersistentStore:
. For more details, see Versioning.)
© 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-02-08)