This paper is divided into three parts:

The first and second sections mainly describe the concept and application of automatic release pool. The second section also details the relationship between autoRelease and method return value. The sample code involved is applied in automatic release pool.

Iii explores the principle of automatic release pool, but does not have more description of the source code, just describes the mechanism of operation. Related sample code in automatic release – principle.

Objc source code mentioned in this article is from objC source code, version 723.

I. Automatic release pool

An autorelease pool, or autorelease pool, is a mechanism that exists in the MRC and makes it possible to “delay the release of objects”.

After an object is added to the automatic release pool, the system releases the object at an appropriate time.

Whether MRC or ARC, the mechanism of automatic release pool is the same, and different keywords represent the same meaning. Such as autoRelease and __autoRelease, @autoreleasepool{}, but it is important to note that NSAutoreleasePool is different from the previous mechanisms.

1.1 MRC

1.2 the ARC

Another common use under ARC is to reduce peak memory

Autorelease and method return values

Another common scenario for autorelease in the MRC era was method return values.

Here, we declare a class and return a class object in different ways:

@interface BFPerson : NSObject

@property (nonatomic, retain) NSString *name;

- (instancetype)initWithName:(NSString *)name;
+ (instancetype)personWithName:(NSString *)name;

@end
Copy the code

According to Apple’s naming rules, -initWithName is a retained return value. The retained return value is not released inside the method. The caller owns the object and needs to release it.

-personWithName: is an unretained return value, which is released internally but delayed. The caller does not own the object and does not need to release it.

2.1 retained the return value

2.2 unretained return value

Third, the principle of

The secret to automatic pool release is "automatic", which reminds us of RunLoop, the most common "automatic" mechanism in iOS. And the release pool, which is a pool, is actually a data structure that needs to support objects in the pool that can send 'release' messages at the right time. So, to understand the mechanics of an automatic release pool, there are two goals: ** to know when the "automatic" release is **, and ** how to build the pool **.Copy the code

3.1 the pool

Let’s try the following code first:

    @autoreleasepool {
        BFPerson *person = [[[BFPerson alloc] init] autorelease];
    }
Copy the code

Convert it to C++ :

$ xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc ViewController.m
Copy the code

We get the following:

/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
            BFPerson *person = ((BFPerson *(*)(id, SEL))(void *)objc_msgSend)((id)((BFPerson *(*)(id, SEL))(void *)objc_msgSend)((id)((BFPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("BFPerson"), sel_registerName("alloc")), sel_registerName("init")), sel_registerName("autorelease"));
}
Copy the code

__AtAutoreleasePool __autoreleasepool. Yes, this is the pool itself.

Struct __AtAutoreleasePool {// constructor __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush(); } // destructor ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atAutoReleasepoolobj); } void * atautoreleasepoolobj; };Copy the code

According to its construction and destructor, the final conversion is:

The objc source code corresponds to the following functions:

void *objc_autoreleasePoolPush(void)
{
    return AutoreleasePoolPage::push();
}
void objc_autoreleasePoolPop(void *ctxt)
{
    AutoreleasePoolPage::pop(ctxt);
}
Copy the code

In fact, AutoreleasePoolPage is the real structure for managing AutoRelease objects.

The AutoreleasePoolPage object structure is shown above, and its storage structure is shown below:

The 'AutoreleasePoolPage' pool is responsible for the management of all 'AutoRelease' objects. In addition to storing its own member variables, the remaining space is used to store 'AutoRelease' objects. If the current Page is not enough, a new Page will be created. And double-linked, and then the 'autoRelease' object is stored in the new Page. The 'next' pointer points to the next location for the 'autoRelease' object.Copy the code

3.2 the timing

Knowing the structure of its auto-release pool leaves the question of how to trigger the auto-release.

Before we understand this timing, let’s take a look at what push and pop do in the C++ code rewritten above.

Push and POP are the two actions that perform the cleanup. So when these two actions are called, the timing, is what we need to talk about.

We explained how RunLoop schedules autoreleasepool in the RunLoop (4) application.

The code that executes on the main thread is usually written inside such callbacks as event callbacks and Timer callbacks. These callbacks are surrounded by AutoreleasePool created by RunLoop, so there is no memory leak and the developer does not have to show that the Pool was created.

At startup, two observers are registered in Runloop.

  • The first Observer listens
    • About to enter the Loop, objc_autoreleasePoolPush() is called in its callback to add a sentinel object flag to the current AutoreleasePoolPage to create the automatic release pool. The order of this Observer is -2147483647, the highest priority, ensuring that it occurs before any callback operation.
  • The second Observer listens
    • Going to sleep: objc_autoreleasePoolPop() and objc_autoreleasePoolPush() are called to clean up from the newly added object until the sentry object is encountered.
    • About to exit RunLoop: objc_autoreleasePoolPop() is called torelease objects in the pool automatically. The order of this Observer is 2147483647, which has the lowest priority and is guaranteed to occur after all callbacks.

Finally, we draw the following figure:

reference

link

  1. Autorelease behind the black screen
  2. NSError and __autoreleasing
  3. Transitioning to ARC Release Notes
  4. Objc source

The sample code

  1. Automatic release pool – Application
  2. Automatic release – Principle