Home > Mobile >  Why does a new Objective-C project's boilerplate contain an autorelease pool block, but a new S
Why does a new Objective-C project's boilerplate contain an autorelease pool block, but a new S

Time:04-22

#import <Cocoa/Cocoa.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
    }
    return NSApplicationMain(argc, argv);
}

Why is this important enough that boilerplate includes it in a new Objective-C project but not a new Swift one?

CodePudding user response:

Xcode's project templates aren't documented in any meaningful way, so it's not possible to give a definitive answer — but, there are a few likely contributing factors, mostly historical.

  • Before the introduction of ARC helping automate reference counting, Objective-C required entirely manual memory management. One strategy for more loosely managing allocations in an "automated" way was using -autorelease to dispose of an object eventually by adding it to a global (possibly-nested) pool of objects that could be disposed when the pool itself was disposed of. This was itself manual through the creation of autorelease pools with -[[NSAutoreleasePool alloc] init] and -[NSAutoreleasePool drain]/-[NSAutoreleasePool release]. When calling -autorelease on an object, the Obj-C runtime would find the "closest" active autoreleasepool and register the object with that pool, to be disposed of once the pool went away.

  • In order to be able to -autorelease an object, there had to be an autorelease pool actually active to capture the object — it doesn't appear to be this way anymore, but -autoreleaseing an object outside of any pools used to log an error (since nothing could really safely be done except leak the object forever). In order to avoid this, the default Xcode template added an implicit autoreleasepool around the entirety of the code in main, to ensure that there was at least some pool active in order to capture objects without error. (In fact, before the introduction of @autoreleasepool { ... } blocks, which implicitly creates an autoreleasepool before the execution of the contained code, and releases it after, the Xcode template used to manually create an autoreleasepool and release it before returning from main)

  • The advent of ARC made autoreleasing significantly less necessary, so much so that Swift doesn't even have a native concept of autoreleasepools. (autoreleasepool in Swift is actually a function from the ObjectiveC module which calls out to the Obj-C runtime to wrap the invoked closure in an autoreleasepool.) Although occasionally useful, they're not typically necessary except when interfacing with Objective-C code which still uses manual memory management and vends autoreleased objects, especially in a tight loop. This comes up occasionally when interfacing with (mostly Apple-based) frameworks like Foundation, which might still have components written with manual memory management in mind

  • There's also the matter of the usefulness of a global autoreleasepool created this way: since the outermost autoreleasepool created this way will only release objects right before program exit, objects released to the default outermost pool are almost effectively leaked for the duration of execution, since there's nothing that will clean them up earlier

So between a lack of need in Swift, a lack of utility, and the non-existence of autoreleasing as a concept outside of Darwin platforms, there's really not much of a need for Xcode to so directly expose the concept in Swift project templates like it used to be necessary for Objective-C. Likely for brevity, not paying the cost of the creation of a pool, and not confusing non-Obj-C code authors, this was left out of the template.

  • Related