Memory Management in Objective-C

The goal of any memory management system is to reduce the memory footprint of a program. This is done by controlling the lifetime of objects created within the program. Good practice with memory management is to make sure objects exist as long as they have to, but not a nanosecond longer.

iOS and OS X applications have crafted a strategy of object ownership. Internally, a designated reference-counting system tracks how many owners each object has. When ownership of an object is claimed, reference count increase by one. The reverse is also true. After the object is released, (when you’re done with the object), you decrease its reference count. As long as a the reference count is greater than zero, an object is guaranteed to exist. However, as soon as the count reaches zero, the operating system is allowed to destroy it.

In the past, developers manually controlled an object’s reference count by calling special memory-management methods defined by the NSObject protocol. This is called Manual Retain Release (MRR). However, Xcode 4.2 introduced Automatic Reference Counting (ARC), which automatically inserts all of these method calls for you.

Don’t Crash!

Manually controlling object ownership can be cumbersome and a daunting task mainly because a programmer must remember to relinquish ownership once finished with the object. This is a necessary, but not always practical routine. In practice, this means that a programmer needs to balance every alloc, retain, and copy call with a release or autorelease on the same object.

If one forgets to balance these calls, the result will be one of two outcomes: a memory leak or a dangling pointer. Forgetting to release an object will mean that its underlying memory is never freed, resulting in a memory leak. Mini leaks won’t have a noticeable effect on your program. However, if you eat up enough memory, your program will eventually crash! On the other hand, if you try to release an object too many times, you’ll have what’s called a dangling pointer. When you try to access the dangling pointer, you’ll be requesting an invalid memory address, and again your program will most likely crash!

Automatic Reference Counting (ARC)

Automatic Reference Counting is a recent development through Xcode 4.2 which eliminates the need for manually maintaining object life-cycles, by allowing the compiler (LLVM) to keep track. How does it do this? By adding code at compile time, the software ensures that objects live as long as needed. ARC works because the runtime knows for each object, how many objects are referencing it.

Strong v. Weak

References between objects are either strong or weak. A strong reference indicates ownership; A strong property is one where you increment the reference count of the object. The referring object owns the referenced object. A weak reference implies that the referring object does not own the referenced object. Weak references don’t increment the reference count of the object. The lifetime of an object is determined by how many strong references there are to it. An object is not freed as long as there is a strong reference to it. _weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.

Under ARC, strong is the default for object types. An object remains “alive” as long as there is a strong pointer to it.

Atomic and Nonatomic

Atomicity has to do with how the class/object behaves in a multi-threaded environment. An accessor that is atomic ensures that it’s value is completely set or retrieved in the thread that is accessing it.

An atomic accessor is considered to be thread safe within the context of setting or getting that property.

Atomic accessors do not ensure that the entire class to be thread safe. They only ensure that the specific property will never be accessed while it’s being set.

Making accessors atomic has a performance impact because they are extra instructions the compiler has to execute whenever accessing your values.

Make them atomic when you might use threads.

Make them non-atomic when you know they will never be access in a threaded environment. Thus, nonatomic is considerably faster than “atomic”.

Nonatomic is used to denote that the object being referenced is not thread safe. This means that the object is not able to deal with multiple requests at the same time.