- The Stack
- The Heap
- Pointer Variables and Object Ownership
- Strong and Weak References
- Properties
- For the More Curious: Property Synthesis
- For the More Curious: Autorelease Pool and ARC History
For the More Curious: Autorelease Pool and ARC History
Before automatic reference counting (ARC) was added to Objective-C, we had manual reference counting. With manual reference counting, ownership changes only happened when you sent an explicit message to an object.
[anObject release]; // anObject loses an owner [anObject retain]; // anObject gains an owner
This was a bummer: Forgetting to send release to an object before setting a pointer to point at something else would create a memory leak. Sending release to an object if you had not previously sent retain to the object was a premature deallocation. A lot of time was spent debugging these problems, which could become very complex in large projects.
During the dark days of manual reference counting, Apple was contributing to an open source project known as the Clang static analyzer and integrating it into Xcode. You will see more about the static analyzer in Chapter 14, but the basic gist is that it could analyze code and tell you if you were doing something silly. Two of the silly things it could detect were memory leaks and premature deallocations. Smart programmers would run their code through the static analyzer to detect these problems and then write the necessary code to fix them.
Eventually, the static analyzer got so good that Apple thought, “Why not just let the static analyzer insert all of the retain and release messages?” Thus, ARC was born. People rejoiced in the streets, and most memory management problems became a thing of the past.
Another thing programmers had to understand in the days of manual reference counting was the autorelease pool. When an object was sent the message autorelease, the autorelease pool would take ownership of an object temporarilyso that it could be returned from the method that created it without burdening the creator or the receiver with ownership responsibilities. This was crucial for convenience methods that created a new instance of some object and returned it:
+ (BNRItem *)someItem { BNRItem *item = [[[BNRItem alloc] init] autorelease]; return item; }
Because you had to send the release message to an object to relinquish ownership, the caller of this method had to understand its its ownership responsibilities. But it was easy to get confused.
BNRItem *item = [BNRItem someItem]; // I guess I own this now? NSString *string = [item itemName]; // Well, if I own that, do I own this?
Thus, objects created by methods other than alloc and copy would be sent autorelease before being returned, and the receiver of the object would take ownership as needed or just let it be destroyed when the autorelease pool was drained.
With ARC, this is done automatically (and sometimes optimized out completely). An autorelease pool is created by the @autoreleasepool directive followed by curly braces. Inside those curly braces, any newly instantiated object returned from a method that does not have allocor copy in its name is placed in that autorelease pool. When the curly brace closes, any object in the pool loses an owner.
@autoreleasepool { // Get a BNRItem back from a method that created it, // method does not say alloc/copy BNRItem *item = [BNRItem someItem]; } // Pool is drained, item loses an owner and is destroyed
iOS applications automatically create an autorelease pool for you, and you really do not have to concern yourself with it. But isn't it nice to know what that @autoreleasepool is for?