Auto-release Pools and Background Threads

In Objective-C on macOS and iOS, an autorelease pool holds objects that were sent an autorelease message and releases them later, when the pool is drained. This page explains when you need to manage pools yourself — which matters whenever you call a library, such as Chilkat, that returns autoreleased objects.

Jump to: Command-line tools Loops Secondary threads ARC GCD & queues

Most application code does not need to create an autorelease pool manually. AppKit and UIKit automatically create and drain a pool around each pass through the main event loop — for example, when a macOS app handles a mouse event, or an iOS app handles a touch event, the framework provides the pool for that unit of work. There are, however, several situations where you should create your own.

Why this matters for Chilkat Chilkat methods return autoreleased objects (NSString, NSData, Cko objects, etc.). On the main thread the framework drains the pool for you, but if you call Chilkat from a secondary thread you created, or in a tight loop, wrap the work in an @autoreleasepool block so those objects are released promptly — otherwise memory can grow in a way that looks like a leak.

Command-line tools

A Foundation-based command-line program has no AppKit or UIKit event loop to create a pool for you. Wrap the main body of the program in an @autoreleasepool block:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // Program code here.
    }
    return 0;
}

Loops that create many temporary objects

If a loop creates many temporary Objective-C objects, those autoreleased objects can accumulate until the outer pool is drained, growing the program's peak memory usage unnecessarily. Place an @autoreleasepool block inside the loop:

for (int i = 0; i < count; i++) {
    @autoreleasepool {
        // Create and use temporary Objective-C objects here.
        // They are released at the end of this iteration.
    }
}

This is especially useful when processing many files, large collections, images, strings, XML documents, JSON objects, or other short-lived Foundation/Cocoa objects.

Secondary threads

If you create a secondary thread yourself — for example with NSThread or a lower-level thread API — create an autorelease pool near the beginning of the thread's entry point. Otherwise, autoreleased objects created on that thread may not be released promptly, which can look like a memory leak:

- (void)threadMain {
    @autoreleasepool {
        // Code executed by the secondary thread.
    }
}

If the thread runs a long-lived loop, it is usually better to place the pool inside the loop so temporary objects are released after each iteration:

- (void)workerThreadMain {
    while (!shouldStop) {
        @autoreleasepool {
            // Perform one unit of work.
        }
    }
}

ARC does not eliminate autorelease pools

Automatic Reference Counting (ARC) manages most retain and release calls for you, but autorelease pools still exist. Objective-C and Foundation APIs may still return autoreleased objects, and temporary objects can still accumulate until the current pool is drained.

Under ARC you normally do not call retain, release, or autorelease yourself — you simply use @autoreleasepool blocks when you need more control over when temporary objects are released.

Grand Central Dispatch and operation queues

With higher-level concurrency APIs such as Grand Central Dispatch (GCD) or operation queues, the system generally manages the thread machinery for you. Even so, an explicit @autoreleasepool block can still help inside a dispatched block or operation that creates many temporary objects:

dispatch_async(queue, ^{
    @autoreleasepool {
        // Work that creates many temporary Foundation/Cocoa objects.
    }
});

This is not always required, but it is good defensive practice for memory-intensive background work.