NSCoder
Inherits From:
NSObject
Conforms To:
NSObject (NSObject)
Declared In:
Foundation/NSCoder.h
Foundation/NSGeometry.h
Foundation/NSCompatibility.h
Class Description
NSCoder is an abstract class that declares the interface used by subclasses to take data from memory and code them into and out of some other format. The NSCoder abstract class declares the interface used by concrete subclasses to transfer objects and other Objective-C data items between memory and some other format. This capability provides the basis for archiving (where objects and data items are stored on disk) and distribution (where objects and data items are copied between different processes or threads). The concrete subclasses provided by Foundation for these purposes are NSArchiver, NSUnarchiver, and NSPortCoder. Concrete subclasses of NSCoder are referred to in general as coder classes, and instances of these classes as coder objects (or simply coders). A coder object that can only encode values is referred to as an encoder object, and one that can only decode values as a decoder object.
NSCoder operates on id
's, scalars, C arrays, structures, and strings, and on pointers to these types. It does not handle types whose implementation varies across platforms, such as union
, void
*, function pointers, and long chains of pointers. It can also operate on user-defined structures as well as pointers to any of these data types. A coder object stores object type information along with the data, so an object decoded from a stream of bytes is normally of the same class as the object that was originally encoded into the stream. An object can change its class when encoded, however; this is described in the NSCoding protocol specification under ""Making Substitutions During Coding"."
Encoding and Decoding Objects and Data Items
To encode or decode an object or data item, you must first create a coder object, then send it a message defined by NSCoder or by a concrete subclass to actually encode or decode the item. NSCoder itself defines no particular method for creating a coder; this typically varies with the subclass. NSArchiver and NSUnarchiver, for example, useinitForWritingWithMutableData:
and initForReadingWithData:
. NSPortCoders are created and used by NSConnection objects; you never create one of these yourself.
To encode an object or data item, use any of the encode...
methods, such as encodeRootObject:
, encodeValueOfObjCType:at:
, and so on. This sample code fragment uses the NSArchiver concrete subclass of NSCoder to archive a custom object called myMapView
:
MapView *myMapView; /* Assume this exists. */
NSMutableData *data
NSArchiver *archiver;
BOOL result;
data = [NSMutableData data];
archiver = [[NSArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeRootObject:myMapView];
result = [data writeToFile:@"/tmp/MapArchive" atomically:YES];
NSArchiver also provides a convenience method for archiving directly to a file, rendering the example above as:
result = [NSArchiver archiveRootObject:myMapView toFile:@"/tmp/MapArchive"];
To decode an object or data item, simply use the decode...
method corresponding to the original encode...
method (as given in the individual method descriptions). Matching these is important, as the method originally used determines the format of the encoded data. See the NSCoding protocol specification for an example.
NSCoder's interface is quite general. Concrete subclasses aren't required to properly implement all of NSCoder's methods, and may explicitly restrict themselves to certain types of operations. For example, NSArchiver doesn't implement the decode...
methods, and NSUnarchiver doesn't implement the encode...
methods.
When to Retain a Decoded Object
You can decode an object value in two ways. The first is explicitly, using thedecodeObject
method (or any decode...Object
method). When decoding an object explicitly you must follow the object ownership convention, and retain the object returned if you intend to keep it. Otherwise the object is owned by the coder and will be released when the coder is released.
The second means of decoding an object is implicitly, using the decodeValueOfObjCType:at:
method or one of its variants, decodeArrayOfObjCType:count:at:
and decodeValuesOfObjCTypes:
. These methods fill a value already claimed by the invoker, so you are responsible for releasing decoded object values. This behavior can prove useful for optimizing large decoding operations, as it obviates the need for sending a retain
message to each decoded object.
Managing Object Graphs
Objects frequently contain pointers to other objects, which may in turn contain pointers to other objects. When analyzed, a group of objects may contain circular references or one object may be referred to by several other objects. In these cases, the objects form an object graph and require special encoding methods to preserve the graph structure. NSCoder declares the following methods to manage object graphs:encodeRootObject:
, encodeObject:
, and encodeConditionalObject:
.
As implemented by a subclass, encodeRootObject:
should encode the object and any objects to which it refers. It is the responsibility of the overriding encodeRootObject:
method to keep track of multiple references to objects, thus preserving the structure of any object graphs.
The encodeConditionalObject:
method allows an object to be excluded from the encoding process. Objects are encoded unconditionally by default, that is, the contents of the object are always encoded. Subclasses can implement encodeConditionalObject:
to encode an object only if it was encoded previously by a call to a method other than encodeConditionalObject:
.
NSCoder's implementations of encodeRootObject:
and encodeConditionalObject:
simply encode the object unconditionally, whether or not it's already been encoded. A concrete subclass that supports object graphs must override these two methods. See the NSArchiver class specification for more information on managing object graphs.
Creating a Subclass of NSCoder
If you define a subclass of NSCoder, at a minimum your subclass must override the following methods:
encodeValueOfObjCType:at:
decodeValueOfObjCType:at:
encodeDataObject:
decodeDataObject:
versionForClassName:
In addition, your subclass may override other methods to provide specialized handling for certain situations. In particular, you can implement any of the following methods:
(an initialization method)encodeRootObject:
encodeConditionalObject:
encodeBycopyObject:
encodeByrefObject:
decodeObject
setObjectZone:
objectZone
See the individual method descriptions for more information. See also the NSArchiver class specification for an example of a concrete subclass.
Note that encodeObject:
and decodeObject
are not among the basic methods. They're defined abstractly to invoke encodeValueOfObjCType:at:
or decodeValueOfObjCType:at:
with an Objective-C type code of "@". Your implementations of the latter two methods must handle this case, invoking the object's encodeWithCoder:
or initWithCoder:
method and sending the proper substitution messages (as described in the NSCoding protocol specification) to the object before encoding it and after decoding it.
With objects, the object being coded is fully responsible for coding itself. However,a few classes hand this responsibility back to the coder object, either for performance reasons or because proper support depends on more information than the object itself has. The two notable classes in Foundation that do this are NSData and NSPort. NSData's low-level nature makes optimization important. For this reason, an NSData object always asks its coder to handle its contents directly using the encodeDataObject:
and decodeDataObject:
methods described in this class specification. Similarly, an NSPort object asks its coder to handle it using the encodePortObject:
and decodePortObject:
methods (which only NSPortCoder implements). This is because an NSPort represents information kept in the operating system itself, which requires special handling for transmission to another process.
These special cases don't affect users of coder objects, since the redirection is handled by the classes themselves in their NSCoding protocol methods. An implementor of a concrete coder subclass, however, must encode NSData and NSPort objects itself, and take care not to send an encodeWithCoder:
or initWithCoder:
message to the NSData or NSPort object. Failure to do so can result in an infinite loop.
- Encoding data
- - encodeArrayOfObjCType:count:at:
- - encodeBycopyObject:
- - encodeByrefObject:
- - encodeBytes:length:
- - encodeConditionalObject:
- - encodeDataObject:
- - encodeNXObject:
- - encodeObject:
- - encodePropertyList:
- - encodePoint:
- - encodeRect:
- - encodeRootObject:
- - encodeSize:
- - encodeValueOfObjCType:at:
- - encodeValuesOfObjCTypes:
- - encodeBycopyObject:
- - encodeArrayOfObjCType:count:at:
- Decoding data
- - decodeArrayOfObjCType:count:at:
- - decodeBytesWithReturnedLength:
- - decodeDataObject
- - decodeNXObject
- - decodeObject
- - decodePropertyList
- - decodePoint
- - decodeRect
- - decodeSize
- - decodeValueOfObjCType:at:
- - decodeValuesOfObjCTypes:
- - decodeBytesWithReturnedLength:
- - decodeArrayOfObjCType:count:at:
- Managing zones
- - objectZone
- - setObjectZone:
- - objectZone
- Getting version information
- - systemVersion
- - versionForClassName:
- - systemVersion
Instance Methods
decodeArrayOfObjCType:count:at:
- (void)decodeArrayOfObjCType:
(const char *)itemTypecount:
(unsigned int)countat:
(void *)address
Decodes an array of count items, whose Objective-C type is given by itemType. The items are decoded into the buffer beginning at address, which must be large enough to contain them all. itemType must contain exactly one type code. NSCoder's implementation invokes decodeValueOfObjCType:at:
to decode the entire array of items. If you use this method to decode an array of Objective-C objects, you are responsible for releasing each object.
This method matches an encodeArrayOfObjCType:count:at:
message used during encoding.
For information on creating an Objective-C type code suitable for itemType, see the description of the @encode()
compiler directive in Object-Oriented Programming and the Objective-C Language.
See also:
- decodeValuesOfObjCTypes:
decodeBytesWithReturnedLength:
- (void *)decodeBytesWithReturnedLength
:
(unsigned int *)numBytes
Decodes a buffer of data whose types are unspecified. NSCoder's implementation invokes decodeValueOfObjCType:at:
to decode the data as a series of bytes, which this method then places into a buffer and returns. The buffer's length is returned by reference in numBytes. If you need the bytes beyond the scope of the current autorelease pool, you must copy them.
This method matches an encodeBytes:length:
message used during encoding.
See also:
- encodeArrayOfObjCType:count:at:
decodeDataObject
- (NSData *)decodeDataObject
Must be overridden by subclasses to decode and return an NSData object.
The implementation of your overriding method must match the implementation of your encodeDataObject:
method. For example, a typical encodeDataObject:
method encodes the number of bytes of data followed by the bytes themselves. Your override of this method must read the number of bytes, create an NSData object of the appropriate size, and decode the bytes into the new NSData object. Your overriding method should send an autorelease
message to the new NSData object before returning it.
decodeNXObject
- (Object *)decodeNXObject
Decodes and returns an object descended from the Object class of NEXTSTEP Release 3 or earlier. Clients do not need to retain the returned object.
This method matches an encodeNXObject:
message used during encoding.
decodeObject
- (id)decodeObject
Decodes an Objective-C object that was previously encoded with any of the encode...Object:
methods. NSCoder's implementation invokes decodeValueOfObjCType:
to decode the object data.
Subclasses may need to override this method if they override any of the corresponding encode...Object:
methods. For example, if an object was encoded conditionally using the encodeConditionalObject:
method, this method needs to check whether the object had actually been encoded.
See also:
- encodeBycopyObject:, - encodeByrefObject:, - encodeObject:
decodePoint
- (NSPoint)decodePoint
Decodes and returns an NSPoint
structure that was previously encoded with encodePoint:
. Subclasses should not override this method.
decodePropertyList
- (id)decodePropertyList
Decodes a property list that was previously encoded with encodePropertyList:
. Subclasses should not override this method. See the NSPPL class specification for information on property lists.
decodeRect
- (NSRect)decodeRect
Decodes and returns an NSRect
structure that was previously encoded with encodeRect:
. Subclasses should not override this method.
decodeSize
- (NSSize)decodeSize
Decodes and returns an NSSize
structure that was previously encoded with encodeSize:
. Subclasses should not override this method.
decodeValueOfObjCType:at:
- (void)decodeValueOfObjCType:
(const char *)valueType at:
(void *)data
Decodes a single value, whose Objective-C type is given by valueType. valueType must contain exactly one type code and the buffer specified by data must be large enough to hold the value corresponding to that type code. For information on creating an Objective-C type code suitable for valueType, see the description of the @encode()
compiler directive in Object-Oriented Programming and the Objective-C Language.
Subclasses must override this method and provide an implementation to decode the value. In your overriding implementation, decode the value into the buffer beginning at data. If your overriding method is capable of decoding an Objective-C object, your method must also retain that object. Clients of this method are then responsible for releasing the object.
This method matches an encodeValueOfObjCType:at:
message used during encoding.
See also:
- decodeArrayOfObjCType:count:at:
, - decodeValuesOfObjCTypes:
, - decodeObject
decodeValuesOfObjCTypes:
- (void)decodeValuesOfObjCTypes:
(const char *)valueTypes, ...
Decodes a series of potentially different Objective-C types. valueTypes is a single string containing any number of type codes. The variable arguments to this method consist of one or more pointer arguments, each of which specifies the buffer in which to place a single decoded value. For each type code in valueTypes, you must specify a corresponding pointer argument whose buffer is large enough to hold the decoded value. If you use this method to decode Objective-C objects, you are responsible for releasing them.
This method matches an enc
odeValuesOfObjCTypes
:
message used during encoding.
NSCoder's implementation invokes decodeValueOfObjCType:at:
to decode individual types. Subclasses that implement the decodeValueOfObjCType:at:
method do not need to override this method.
For information on creating Objective-C type codes suitable for valueTypes, see the description of the @encode()
compiler directive in Object-Oriented Programming and the Objective-C Language.
See also:
- decodeArrayOfObjCType:count:at:
encodeArrayOfObjCType:count:at:
- (void)encodeArrayOfObjCType:
(const char *)itemTypecount:
(unsigned int)countat:
(const void *)address
Encodes an array of count items, whose Objective-C type is given by itemType. The values are encoded from the buffer beginning at address. itemType must contain exactly one type code. NSCoder's implementation invokes encodeValueOfObjCType:at:
to encode the entire array of items. Subclasses that implement the encodeValueOfObjCType:at:
method do not need to override this method.
This method must be matched by a subsequent decodeArrayOfObjCType:count:at:
message.
For information on creating an Objective-C type code suitable for itemType, see the description of the @encode()
compiler directive in Object-Oriented Programming and the Objective-C Language.
See also:
- encodeValueOfObjCType:at:
, - encodeValuesOfObjCTypes:
, - encodeBytes:length:
encodeBycopyObject:
- (void)encodeBycopyObject:
(id)object
Can be overridden by subclasses to encode object so that a copy rather than a proxy is created upon decoding. NSCoder's implementation simply invokes encodeObject:
.
This method must be matched by a subsequent decodeObject
message.
See also:
- encodeRootObject:
, - encodeConditionalObject:
, - encodeNXObject:
,
- encodeByrefObject:
encodeByrefObject:
- (void)encodeByrefObject:
(id)object
Can be overridden by subclasses to encode object so that a proxy, rather than a copy, is created upon decoding. NSCoder's implementation simply invokes encodeObject:
.
This method must be matched by a subsequent decodeObject message.
See also:
- encodeBycopyObject:
,- replacementObjectForPortCoder
:
encodeBytes:length:
- (void)encodeBytes
:
(void *)address length:
(unsigned int)numBytes
Encodes a buffer of data whose types are unspecified. The buffer to be encoded begins at address, and its length in bytes is given by numBytes.
This method must be matched by a subsequent decodeBytesWithReturnedLength:numBytes:
message.
See also:
- encodeArrayOfObjCType:count:at:
encodeConditionalObject:
- (void)encodeConditionalObject:
(id)object
Can be overridden by subclasses to conditionally encode object, preserving common references to that object. In the overriding method, object should be encoded only if it's unconditionally encoded elsewhere (with any other encode...Object:
method).
This method must be matched by a subsequent decodeObject
message. Upon decoding, if object was never encoded unconditionally, decodeObject
returns nil
in place of object. However, if object was encoded unconditionally, all references to object must be resolved.
NSCoder's implementation simply invokes encodeObject:
.
See also:
- encodeRootObject:
, - encodeObject:
, - encodeBycopyObject:
, - encodeNXObject:
,
- encodeConditionalObject:
(NSArchiver)
encodeDataObject:
- (void)encodeDataObject:
(NSData *)data
Must be overridden by subclasses to encode the NSData object data. This method must be matched by a subsequent decodeDataObject
message.
See also:
- encodeObject:
encodeNXObject:
- (void)encodeNXObject:
(Object *)nxobject
Encodes nxobject, an object descended from the Object class of NEXTSTEP Release 3 or earlier. This method must be matched by a subsequent decodeNXObject
message.
Objects encoded more than once by successive invocations of this method are written in their entirety on each invocation. Applied to an object graph, the behavior of this method effectively flattens the graph structure, creating a new copy of the object in place of a reference to the original. This differs from the behavior of encodeObject:
, which encodes an object once and replaces subsequent occurences of the object with a reference to the original.
See also:
- encodeConditionalObject:
, - encodeBycopyObject:
, - encodeRootObject:
encodeObject:
- (void)encodeObject:
(id)object
Encodes object. NSCoder's implementation simply invokes encodeValueOfObjCType:at:
to encode the object. Subclasses can override this method to encode a reference to object instead of object itself. For example, NSArchiver detects duplicate objects and encodes a reference to the original object rather than encode the same object twice.
This method must be matched by a subsequent decodeObject
message.
See also:
- encodeRootObject:
, - encodeConditionalObject:
, - encodeBycopyObject:
,
- encodeNXObject:
encodePoint:
- (void)encodePoint:
(NSPoint)point
Encodes point. NSCoder's implementation invokes encodeValueOfObjCType:at:
to encode point. Subclasses should not need to override this method.
This method must be matched by a subsequent decodePoint
message.
encodePropertyList:
- (void)encodePropertyList:
(id)aPropertyList
Encodes a property list. (See the NSPPL class specification for information on property lists.) NSCoder's implementation invokes encodeValueOfObjCType:at:
to encode aPropertyList. Subclasses should not need to override this method.
This method must be matched by a subsequent decodePropertyList
message.
encodeRect:
- (void)encodeRect:
(NSRect)rect
Encodes rect. NSCoder's implementation invokes encodeValueOfObjCType:at:
to encode rect. Subclasses should not need to override this method.
This method must be matched by a subsequent decodeRect
message.
encodeRootObject:
- (void)encodeRootObject:
(id)rootObject
Can be overridden by subclasses to encode an interconnected group of Objective-C objects, starting with rootObject. NSCoder's implementation simply invokes encodeObject:
.
This method must be matched by a subsequent decodeObject
message.
See also:
- encodeObject:
, - encodeConditionalObject:
, - encodeBycopyObject:
, - encodeNXObject:
,
- encodeRootObject:
(NSArchiver)
encodeSize:
- (void)encodeSize:
(NSSize)size
Encodes size. NSCoder's implementation invokes encodeValueOfObjCType:at:
to encode size. Subclasses should not need to override this method.
This method must be matched by a subsequent decodeSize
message.
encodeValueOfObjCType:at:
- (void)encodeValueOfObjCType:
(const char *)valueType at:
(const void *)address
Must be overridden by subclasses to encode a single value residing at address, whose Objective-C type is given by valueType. valueType must contain exactly one type code.
This method must be matched by a subsequent decodeValueOfObjCType
:
at:
message.
For information on creating an Objective-C type code suitable for valueType, see the description of the @encode()
compiler directive in Object-Oriented Programming and the Objective-C Language.
See also:
- encodeArrayOfObjCType:count:at:
, - encodeValuesOfObjCTypes:
encodeValuesOfObjCTypes:
- (void)encodeValuesOfObjCTypes:
(const char *)valueTypes, ...
Encodes a series of values of potentially differing Objective-C types. valueTypes is a single string containing any number of type codes. The variable arguments to this method consist of one or more pointer arguments, each of which specifies a buffer containing the value to be encoded. For each type code in valueTypes, you must specify a corresponding pointer argument.
This method must be matched by a subsequent decodeValuesOfObjCTypes
:
message.
NSCoder's implementation invokes encodeValueOfObjCType:at:
to encode individual types. Subclasses that implement the encodeValueOfObjCType:at:
method do not need to override this method. However, subclasses that provide a more efficient approach for encoding a series of values may override this method to implement that approach.
For information on creating Objective-C type codes suitable for valueTypes, see the description of the @encode()
compiler directive in Object-Oriented Programming and the Objective-C Language.
See also:
- encodeArrayOfObjCType:count:at:
, - encodeValueOfObjCType:at:
objectZone
- (NSZone *)objectZone
Returns the memory zone used to allocate decoded objects. NSCoder's implementation simply returns the default memory zone, as given by NSDefaultMallocZone()
.
Subclasses must override this method and the setObjectZone:
method to allow objects to be decoded into a zone other than the default zone. In its overriding implementation of this method, your subclass should return the current memory zone (if one has been set) or the default zone (if no other zone has been set).
See also:
- setObjectZone:
setObjectZone:
- (void)setObjectZone:
(NSZone *)zone
Can be overridden by subclasses to set the memory zone used to allocate decoded objects. NSCoder's implementation of this method does nothing.
Subclasses must override this method and the objectZone
method to allow objects to be decoded into a zone other than the default zone. In its overriding implementation of this method, your subclass should store a reference to the current memory zone.
See also:
- objectZone
systemVersion
- (unsigned int)systemVersion
During encoding, this method should return the system version currently in effect. During decoding, this method should return the version that was in effect when the data was encoded.
By default, this method returns the current system version, which is appropriate for encoding but not for decoding. Subclasses that implement decoding must override this method to return the system version of the data being decoded.
versionForClassName:
- (unsigned int)versionForClassName:
(NSString *)className
Must be overridden by subclasses to return the version in effect for the class named className when it was encoded. Returns NSNotFound if no class named
Copyright © 1997, Apple Computer, Inc. All rights reserved.