Unable to find a good article on autoreleasePool online, I decided to write one myself. Start with automatic reference counting in MRC to make it easier to understand @Autoreleasepool in ARC. Advanced Programming in Objective-C
MRC
What is the autorelease
Autorelease treats instance objects like C automatic variables and releases them when they go out of scope, except that autoRelease can be manually scoped.
The use of the autorelease
In MRC we usually use autoRelease in the following situations:
-(id)object{ id = [[NSObject alloc] init]; [obj aoturelease]; // NSAutoreleasePool is not used here, for reasons explained belowreturn obj;
}
Copy the code
Autorelease: Obtains the existence of an object, but does not hold the object itself.
Autorelese provides the ability to release objects automatically and correctly (calling the release method) when they are outside the specified range of life. Autorelease registers the object in autoReleasepool, and when the pool ends (usually when the scope ends), the pool automatically calls Release
How to use autoRelease
- 1. Generate and hold the NSAutoreleasePool object;
- 2. Call the autoreleae instance method of the allocated object.
- 3. Discard the NSAutoreleasePool object.
Sample code:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool id = obj = [[NSObject alloc] init]; [obj autorelease]; [pool drain]; Calling this line of code is equivalent to calling the release method of all objects registered in the pool.Copy the code
Why is NSAutoreleasePool sometimes used and not sometimes used?
Reason: The NSRunLoop of the main loop generates and frees NSAutoreleasePool, so you don’t have to use NSAutoreleasePool for development. That is, even if you don’t generate NSAutoreleasePool, the runtime will automatically generate one.
When do YOU use NSAutoreleasePool objects
While NSRunloop will release generated autoRelease objects, a large number of objects generated in a short period of time will not be released immediately, as follows:
for(int i = 0 ; ; I++){/** * a large number of objects in a short period of time, will not be released immediately, this will cause memory shortage, resulting in a lag.Copy the code
Adding NSAutoreleasePool solves this problem:
for(int i = 0 ; ; i++ ){ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; /** * pool drain; // Release the generated local variables so that objects do not pile up too much}Copy the code
The realization of the autorelease
[obj autorelease];
Copy the code
Let’s take a look at the source code in GNUstep
GNUstep is an interchange of Cocoa frameworks. That is, GNUStep’s source code is not exactly the same as Apple’s Cocoa implementation, but from the user’s point of view they behave and implement the same, or very similar, way. Understanding the GNUstep source code is equivalent to understanding Apple’s Cocoa implementation.
-(id)autorelease
{
[NSAutorelease addObject:self];
}
Copy the code
The essence of the AutoRelease instance method is to call the addObject class method of the NSAutoreleasePool object. An implementation of the addObject method (the source code is complicated, this is the simplified code) :
+(void)addObject:(id)object{NSAutoreleasePool *pool = get the NSAutoreleasePool object in use;if(pool ! = nil){ [pool addObject:object]; // Pool has an array property to add all objects registered in the pool. }else{
//error
}
}
Copy the code
The pool object that you use in the addObject method is the NSAutoreleasePool object that you just generated. If you nested NSAutoreleasePool then the pool you get is your innermost pool object, That is, the NSAutoreleasePool object closest to your object.
[pool drain]; This line of code releases all objects registered in the pool at run time. Let’s look at the drain method implementation.
-(void)drain
{
[self dealloc];
}
-(void)dealloc
{
[self emptyPool];
[array release];
}
-(void)emptyPool
{
for (id obj inarray){ [obj release]; }}Copy the code
Use of Autoreleae in ARC
We cannot use the AutoRelease method while ARC is in effect, nor can we use the NSAutoreleasePool class. But we will have alternatives that are easier to write.
Use the pose
When ARC is invalid:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id = obj = [[NSObject alloc] init];
[obj autorelease];
[pool drain];
Copy the code
When ARC is valid:
@autoreleasepool{
id obj = [[NSObject alloc] init];
}
Copy the code
ARC does not use the __autoreleasing modifier. If you have any questions, please leave a comment
@ autoreleasepool implementation
When you use @Autoreleasepool, the compiler has a replacement code. Your code:
@autoreleasepool{
id obj = [[NSObject alloc] init];
}
Copy the code
Compiler simulation code:
id pool = objc_autoreleasePoolPush();
id = objc_msgSend(NSObject,@selector(alloc));
objc_msgSend(obj,@selector(init));
objc_autorelease(obj);
objc_autoreleasePoolPop(pool);
Copy the code
We can see that the code transformed by the compiler is used exactly the same as our earlier NSAutoreleasePool class, so autoRelease functions exactly the same whether ARC is valid or not.