Object Life Cycle

An object’s life cycle—that is, its runtime life from its creation to its destruction—is marked or determined by various messages it receives. An object comes into being when a program explicitly allocates and initializes it or when it makes a copy of another object. An object can also begin its runtime life during unarchiving, when it is asked to decode itself from the archive byte stream. If an object was unarchived from a nib file, it receives an awakeFromNib message after all objects in the nib file have been loaded into memory


Object life cycle

After the creation and initialization phase, an object remains in memory as long as its retain count is greater than zero. Other objects in the program may express an ownership interest in an object by sending it retain or by copying it, and then later relinquish that ownership interest by sending release to the object. While the object is viable, a program may begin the archiving process, in which the object encodes its state in the archive byte stream. When the object receives its final release message, its retain count drops to zero. Consequently, the object’s dealloc method is called, which frees any objects or other memory it has allocated, and the object is destroyed.



Object creation

An object comes into runtime existence through a two-step process that allocates memory for the object and sets its state to reasonable initial values. To allocate an Objective-C object, send an alloc or allocWithZone: message to the object’s class. The runtime allocates memory for the object and returns a “raw” (uninitialized) instance of the class. It also sets a pointer (known as the isa pointer) to the object’s class, zeros out all instance variables to appropriately typed values, and sets the object’s retain count to 1.
After you allocate an object, you must initialize it. Initialization sets the instance variables of an object to reasonable initial values. It can also allocate and prepare other global resources needed by the object. You initialize an object by invoking an init method or some other method whose name begins with init.. If these methods succeed in initializing an object, they return it; otherwise, they return nil. If an object’s class does not implement an initializer, the Objective-C runtime invokes the initializer of the nearest ancestor instead.

Art/object_creation_2x.png


Memory-Management Implications

In code that explicitly manages memory, the allocation and initialization procedure returns an object with a retain count of 1. This means that the client receiving the object now “owns” the object and is responsible for releasing it. You release it by sending it a release or autorelease message; the latter message causes a delayed release. If you do not release objects that you own, your program will leak memory.

Factory Methods


A factory method is a class method that, as a convenience to clients, creates an instance of a class. A factory method combines allocation and initialization in one step and returns an autoreleased instance of the class. Because the received object is autoreleased, the client must copy or retain the instance if it wants it to persist in memory. The names of factory methods have the following initial form:
+ (id)typeRemainderOfMethodName

Object archiving

Archiving is the process of converting a group of related objects to a form that can be stored or transferred between applications. The end result of archiving—an archive—is a stream of bytes that records the identity of objects, their encapsulated values, and their relationships with other objects. Unarchiving, the reverse process, takes an archive and reconstitutes an identical network of objects.


Archiving

For its instances to be included in an archive, a class must adopt the NSCoding protocol and implement the required methods for encoding and decoding objects. Cocoa archives can hold Objective-C objects, scalar values, C arrays, structures, and strings. Archives store the types of objects along with the encapsulated data, so an object decoded from a stream of bytes is of the same class as the object that was originally encoded into the stream.

1. Keyed and Sequential Archivers : 



The Foundation framework provides two sets of classes for archiving and unarchiving networks of objects. They include methods for initiating the archiving and unarchiving processes and for encoding and decoding the instance data of your objects. Objects of these classes are sometimes referred to as archivers and unarchivers.
  • Keyed archivers and unarchivers (NSKeyedArchiver and NSKeyedUnarchiver). These objects use string keys as identifiers of the data to be encoded and decoded. They are the preferred objects for archiving and unarchiving objects, especially with new applications.
  • Sequential archivers and unarchivers (NSArchiver and NSUnarchiver). This “old-style” archiver encodes object state in a certain order; the unarchiver expects to decode object state in the same order. Their intended use is for legacy code; new applications should use keyed archives instead.

2. Creating and Decoding Keyed Archives


An application creates an archive by invoking the archiveRootObject:toFile: class method of NSKeyedArchiver. The first parameter of this method takes a reference to the root object of an object graph. Starting with this root object, each object in the graph that conforms to the NSCoding protocol is given an opportunity to encode itself into the archive. The resulting byte stream is written to the specified file.
Decoding an archive proceeds in the opposite direction. An application calls the NSKeyedUnarchiver class method unarchiveObjectWithFile:. Given an archive file, the method recreates the object graph, asking the class of each object in the graph to decode the relevant data in the byte stream and recreate the object. The method ends by returning a reference to the root object.
The NSKeyedArchiver class methods archivedDataWithRootObject: and unarchiveObjectWithData: are equivalent to the above methods, except they work with a data object rather than a file.

Memory management

Memory management is the programming discipline of managing the life cycles of objects and freeing them when they are no longer needed. Managing object memory is a matter of performance; if an application doesn’t free unneeded objects, its memory footprint grows and performance suffers. Memory management in a Cocoa application that doesn’t use garbage collection is based on a reference counting model. When you create or copy an object, its retain count is 1. Thereafter other objects may express an ownership interest in your object, which increments its retain count. The owners of an object may also relinquish their ownership interest in it, which decrements the retain count. When the retain count becomes zero, the object is deallocated (destroyed).
Memory management
Memory-Management Rules


Memory-management rules, sometimes referred to as the ownership policy, help you to explicitly manage memory in Objective-C code.
  • You own any object you create by allocating memory for it or copying it.
  • If you are not the creator of an object, but want to ensure it stays in memory for you to use, you can express an ownership interest in it.
    Related method: retain
  • If you own an object, either by creating it or expressing an ownership interest, you are responsible for releasing it when you no longer need it.
    Related methods: releaseautorelease
  • Conversely, if you are not the creator of an object and have not expressed an ownership interest, you must not release it.
If you receive an object from elsewhere in your program, it is normally guaranteed to remain valid within the method or function it was received in. If you want it to remain valid beyond that scope, you should retain or copy it. If you try to release an object that has already been deallocated, your program crashes.

Aspects of Memory Management


The following concepts are essential to understanding and properly managing object memory:
  • Autorelease pools. Sending autorelease to an object marks the object for later release, which is useful when you want the released object to persist beyond the current scope. Autoreleasing an object puts it in an autorelease pool (an instance of NSAutoreleasePool), which is created for an arbitrary program scope. When program execution exits that scope, the objects in the pool are released.
  • Deallocation. When an object’s retain count drops to zero, the runtime calls the dealloc method of the object’s class just before it destroys the object. A class implements this method to free any resources the object holds, including objects pointed to by its instance variables.
  • Factory methods. Many framework classes define class methods that, as a convenience, create objects of the class for you. These returned objects are not guaranteed to be valid beyond the receiving method’s scope.

Object encoding

Object encoding converts an object’s class identity and state to a format that can be stored or transferred between processes. The class type and instance data are written to a byte stream that can persist after a program terminates. When the program is launched again, a newly allocated object can decode the stored representation of itself and restore itself to its previous runtime state. Encoding usually occurs in concert with archiving, which puts a graph of objects into a format (an archive) that can be written to the file system; unarchiving operates on an archive, asking each object in the stored graph to decode itself.
Object encoding is also used in the OS X distributed objects API for transferring objects from one process to another. However, its most common use is for archiving, which like a property list, is a mechanism for object persistence.

Object encoding

How to Encode and Decode Objects

For your subclass to encode and decode its instances, it must conform to the NSCoding protocol and implement two methods: initWithCoder: and encodeWithCoder:. When a program unarchives or archives an object graph, these methods are invoked. In the encodeWithCoder: method, you encode the values of an object’s important instance variables; in the initWithCoder: method, you decode those values and reassign them to their instance variables. If an object receives an initWithCoder: message, none of its initializer methods are invoked.
The sole argument of initWithCoder: and encodeWithCoder: is an NSCoder object whose purpose is to perform the actual decoding or encoding. Because NSCoder is an abstract class, the coder object is in most cases an instance of one of the following concrete subclasses: NSKeyedArchiverNSKeyedUnarchiverNSArchiverNSUnarchiver. The archiver classes declare methods for encoding an object’s instance variables; the unarchiver classes declare methods for decoding instance variables.
The NSCoder methods work on objects, scalars, C arrays, structures, and strings, and on pointers to these types. Before you encode or decode an instance variable of your own class, be sure to first invoke the superclass implementation of initWithCoder: or encodeWithCoder:. When you decode objects from the byte stream, be sure to retain or copy them when you assign them to their instance variables.

Keyed Versus Sequential Archiving

Two of the concrete NSCoder subclasses are different from each other in a fundamental way. The “keyed” archiver class (NSKeyedArchiver and NSKeyedUnarchiver) associate an encoded value with a string key and use that same key when decoding that value; thus instance variables can be encoded and decoded in any sequence. With the other type of coder (NSArchiver and NSUnarchiver) you encode instance variables in a certain sequence, and you must decode them in the same sequence. The sequential coders should be used only with legacy code; new subclasses should use keyed archive coders.

Comments

Post a Comment

Popular posts from this blog

iOS Architecture

Property vs Instance Variable (iVar) in Objective-c [Small Concept but Great Understanding..]

setNeedsLayout vs layoutIfNeeded Explained