Objective-C Memory Management
- Retaining and Releasing
- Assigning to Instance Variables
- Automatic Reference Counting
- Returning Objects via Pointer Arguments
- Avoiding Retain Cycles
- Migrating to ARC
- Autorelease Pools
- Using Autoreleased Constructors
- Autoreleasing Objects in Accessors
- Supporting Automatic Garbage Collection
- Interoperating with C
- Understanding Object Destruction
- Using Weak References
- Allocating Scanned Memory
If you come from a C or C++ background, you’re probably used to tracking ownership of objects and manually allocating and destroying them. If you’re coming from a language such as Java, you’re probably accustomed to having the garbage collector take care of all of this for you.
Objective-C does not, at the language level, provide anything for allocating or deallocating objects. This is left up to C code. You commonly allocate objects by sending their class a +alloc message. This then calls something like malloc() to allocate the space for the object. Sending a -dealloc message to the instance will then clean up its instance variables and delete it.
The Foundation framework adds reference counting to this simple manual memory management. This makes life much easier, once you understand how it works. Newer compilers provide some assistance for you, eliminating the need to write the reference counting code yourself.
Retaining and Releasing
Every object that inherits from NSObject has a reference count associated with it. When this reference count reaches 0, it is destroyed. An object created with +alloc or any of the related methods, such as +new or +allocWithZone:, begins life with a reference count of one.
To control the reference count of an object, you send it -retain and -release messages. As their names would imply, you should use these messages when you want to retain a reference to an object, or when you want to release an existing reference. The -retain message increments the object’s reference count, and the -release message decrements it.
You can also send a -retainCount message to an object to determine its current reference count. It’s tempting to use this for optimization and invoke some special cases when you are sure there is only one reference to an object. This is a very bad idea. As the name implies, this method tells you the number of retained references to the object, not the number of references. It is common not to bother sending a -retain message to objects when you create a pointer to them on the stack. This means that an object may be referenced in two or more places, even though its retain count is only one.
Pointers in Objective-C are divided into two categories: owning references and non-owning references. An owning reference is one that contributes towards the retain count of an object. When you call a method like +new or -retain, you get an owning reference to a new object. Most other methods return a non-owning reference. Instance variables and global variables are typically owning pointers, so you should assign owning references to them. You also need to ensure that you delete the existing owning reference (by sending a -release message) when performing an assignment.
Temporary variables are typically non-owning references. Automatic reference counting and garbage collection, which we’ll look at later in this chapter, both introduce special kinds of non-owning references.