The two basic rules of Memory Management are
- Objects obtained with -alloc, -new, -copy, or -mutableCopy have a retain count of one.
- For objects created with any other method, assume they have a retain count of one but will be autoreleased. If you need to keep them in memory, you need to explicitly retain them.
Lets see in detail how the memory management works,
Memory management concepts are of critical importance and every Cocoa programmer should take the time to master them.
Memory management concepts are of critical importance and every Cocoa programmer should take the time to master them.
Memory management in Cocoa comes in two flavors: classic retain counts and garbage-collected. The question deals with the retain count flavor, so I will focus on that one.
The retain count memory management scheme in Cocoa works on the basis that an object will remain in memory as long as other objects claim to be "interested in it." The Objective-C runtime keeps track of this "interested in" relationship with a simple number: the retain count. It does not matter who is interested in the object, only if anyone is interested in it. Objects that want to keep another object in memory ask that the other's retain count be increased by one, and if they are no longer interested in it may request that it be decreased by one. When the retain count for an object reaches zero, it means that no one is interested in it and it can be destroyed. The methods needed to alter the retain count of an object are inherited from NSObject:
- (id)retain; // Increases the retain count of the object by 1 - (oneway void)release; // Decreases the retain count of the object by 1
The oneway qualifier in the -release return type indicates that the caller will not wait for an answer from the method. This is required for a nifty technology called Distributed Objects, which allows an application to use objects from another process, even from a remote machine.
The value of an object’s retain count can be obtained with the method:
- (NSUInteger)retainCount;
The following snippets illustrate the basic use of these methods. Any class derived from NSObject and created with -alloc begins life with a retain count of one.
NSObject *anObject = [[NSObject alloc] init]; NSLog (@"Retain count = %d", [anObject retainCount]); // Outputs 1 [otherObject doSomethingWith:anObject]; [anObject release]; // Done with the object // Elsewhere in the program: - (void)doSomethingWith:(NSObject *)anObject { [anObject retain]; NSLog (@"Retain count = %d", [anObject retainCount]); // Outputs 2 // ... [anObject release]; }
The example above begins by creating an object with a retain count of one. It is then passed to another method that increases its retain count, does some work with it and then releases it. At this point, anObject has a retain count of one again, so when it is released again after the -doSomethingWith:method returns, it will be destroyed.
You now know that whenever the retain count for an object reaches zero, it will be destroyed. This fact puts a burden of responsibility on you, the programmer. First of all, it means that if you release an object that already has a retain count of zero, your program will crash, because you will be sending a message to an object that no longer exists. Second, if you forget to release an object you no longer need, it will stay in memory while the program runs and waste resources. This situation is known as a memory leak.
When an object is released and reaches a retain count of zero, it is given the opportunity to clean-up after itself. This done by implementing the -dealloc method that is called just before the object is destroyed. In -dealloc you will typically release any objects or resources that are owned by the released object, so that memory leaks are prevented. A typical situation is given below.
- (void)dealloc { [currentDate release]; // current date is an instance variable [myView release]; // myView is an instance variable [super dealloc]; }
Notice how the -dealloc method ends by calling the superclass's -dealloc. That is required and guarantees that clean-up continues all the way up to NSObject. The -dealloc method should never be invoked directly by the programmer. It must be called indirectly as a result of a -release message that decreases the retain count of an object to zero.
The final concept needed to complete this discussion of retain count memory management is autoreleased objects. The need for autoreleased objects arises from the situation illustrated by the method below.
- (MyObject *)returnsAnObject { MyObject *foo = [[MyObject alloc] init]; // Do something with foo return foo; }
The -returnsAnObject method creates an instance of MyObject, manipulates it and then returns it. As written, the object is returned with a retain count of one. That may be OK, but it means that the object will have to be released explicitly later and this could cause confusion if the -returnsAnObject method is part of a library and you have no access to the source code. Adding a [foo release]; statement before returning will result in a crash because the object will be destroyed just before returning it.
The solution is to use the -autorelease method:
- (id)autorelease; // Returns the object being autoreleased.
The -autorelease method means that the object will be released but later on, typically after the current user event is processed. For programming purposes, you can consider that an autoreleased object has a retain count of zero.
The previous example can then be amended to:
- (MyObject *)returnsAnObject { MyObject *foo = [[[MyObject alloc] init] autorelease]; // Do something with foo return foo; // foo is returned with a virtual retain count of zero }
******This tutorial is for my reference and is taken from informit
source: http://www.informit.com/blogs/blog.aspx?uk=Retain-Counts-for-Cocoa-and-iPhone-Programmers
source: http://www.informit.com/blogs/blog.aspx?uk=Retain-Counts-for-Cocoa-and-iPhone-Programmers
Comments
Post a Comment