the problem solved
Everything is produced in the real life of the urgent need for such things, people by thinking about inventing something to solve the problem. Then the automatic release pool is used to solve any problems. Take a look at the following example:
For some messages (methods) that have a return value, the object to which it is returned will be given to release its memory, such as the description message in the NSObject class
-(nsstring*) description{
nsstring *description;
Description = [[NSString alloc]initwithformat:@ "Hello World"];
return (description);
} Description
This time description the memory release of the string to whom to give. Certainly should not be in the description method, so that the returned object points to a freed memory. This is certainly not feasible.
So if the caller were to release it, then it would have to be written like this:
Retaintracker *tracker = [Retaintracker new];
NSString *desc = [Tracker description];
[desc release];
So what's the problem with this writing? No problem, just one more line of code. There is no better way to write a single line of code to achieve the effect of automatic release. Now that there is a need, someone will definitely try to solve the problem.
Workaround
Apple has a concept of an auto-release pool in the Cocoa Framework, which provides a method called Autorelease in the NSObject class.
-(ID) autorelease{};//autorelease
The method pre-sets a release message that will be sent at some time in the future, and the returned ID represents the object that accepted the message. When we call the object's Autorelease method, we actually put the object into the auto-free pool, and when the auto-free pool is destroyed, the release message is sent to all objects in that pool. This time we have modified the description method to the following form:
-(nsstring*) description
{
nsstring *description;
Description = [[NSString alloc]initwithformat:@ "Hello World"];
return ([description autorelease]);
} Description
At this point we just need a word to do the work of memory release at the place where we call. You do not have to add statements that call the release method separately.
Create
We said so much, we're talking about automatic release of the pool can help us to solve the problem of automatic release of objects, but this auto-release pool is not the existence of itself, it needs our own to display the creation. There are 2 ways to create an auto-free pool.
by @autoreleasepool keyword
When you use @autoreleasepool{}, all the code in curly braces will be placed in the pool. However, any variable in the curly brace cannot be used outside the brackets.
by NSAutoreleasePool Object
The object needs to be created, and the code that creates the statement and destroys the statement in that object is the equivalent of putting it into an auto-free pool.
NSAutoreleasePool *pool;
Pool = [NSAutoreleasePool new];
Retaintracker *tracker = [Retaintracker new];
NSString *desc = [Tracker description];
[desc release];
Count:1
[tracker retain];//Count:2
NSLog (@ "%d", [tracker Retaincount]);
[Tracker retain]; Count:3
NSLog (@ "%d", [tracker Retaincount]);
[Tracker release]; Count:2
NSLog (@ "%d", [tracker Retaincount]);
[Tracker release]; Count:1
NSLog (@ "%d", [tracker Retaincount]);
[Tracker retain]; Count 2
NSLog (@ "%d", [tracker Retaincount]);
[Tracker release]; Count 1
NSLog (@ "%d", [tracker Retaincount]);
[Tracker release]; count:0, dealloc it
[pool release];
The above code is an automatic release pool creation process.
Recommended
Use the @autoreleasepool{} keyword first to create an auto-free pool.
Working principle
So how does the auto-release pool work? Here is an example to explain.
#import <Foundation/Foundation.h>
@interface RetainTracker : NSObject
@end // RetainTracker
@implementation RetainTracker
- (id) init
{
if (self = [super init]) {
NSLog (@"init: Retain count of %d.",
[self retainCount]);
}
return (self);
} // init
- (void) dealloc
{
NSLog (@"dealloc called. Bye Bye.");
[super dealloc];
} // dealloc
@end // RetainTracker
int main (int argc, const char * argv[])
{
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
RetainTracker *tracker;
tracker = [RetainTracker new]; // count: 1
[tracker retain]; // count: 2
[tracker autorelease]; // count: still 2
[tracker release]; // count: 1
NSLog (@"releasing pool");
[pool release];
// gets nuked, sends release to tracker
@autoreleasepool
{
RetainTracker *tracker2;
tracker2 = [RetainTracker new]; // count: 1
[tracker2 retain]; // count: 2
[tracker2 autorelease]; // count: still 2
[tracker2 release]; // count: 1
NSLog (@"auto releasing pool");
}
return (0);
}
The first code block is an auto-free pool created using the NSAutoreleasePool object. Compared to the previous statement, there is one more [tracker autorelease] statement, which is what the statement does. Instead of manipulating the value of the reference counter, it adds the object to the auto-free pool, and a reference to the auto-free pool points to the object. When the auto-free pool is destroyed, a release message is sent to the changed object. Since we sent the retain object to the Tracker object, the counter adds 1, and then sends the release message, the counter is minus 1, but at this point the Dealloc method of the tracker object is not called, because the new method lets the counter add 1, Therefore, before the release method of the pool object is called, the value of the counter of the Tracker object is 1, and when the pool object's call to release, the counter for the auto-free pools is 0, at which point the Dealloc method of the pool object is called. Then you want the object in the pool to send the release object, then the Tracker object's counter value becomes the 0,tracker object's Dealloc method is called, so the output should look like this:
2015-02-01 00:12:02.426 09.02 retaincount-2[860:58571] init:retain count of 1.
2015-02-01 00:12:02.428 09.02 retaincount-2[860:58571] Releasing pool
2015-02-01 00:12:02.428 09.02 RetainCount-2[ 860:58571] Dealloc called. Bye Bye.
Another automatic release pool created by the @autoreleasepool keyword is the same process. The entire output is as follows:
2015-02-01 00:18:23.932 09.02 retaincount-2[876:61410] init:retain count of 1.
2015-02-01 00:18:23.933 09.02 retaincount-2[876:61410] Releasing pool
2015-02-01 00:18:23.934 09.02 RetainCount-2[ 876:61410] Dealloc called. Bye Bye.
2015-02-01 00:18:23.934 09.02 retaincount-2[876:61410] init:retain count of 1.
2015-02-01 00:18:23.934 09.02 retaincount-2[876:61410] Auto Releasing pool
2015-02-01 00:18:23.934 09.02 RETAINCOUNT-2[876:61410] Dealloc called. Bye Bye.
Program ended with exit code:0