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.