Cocoa Programming for Mac OS X - Aaron Hillegass [25]
Clearly, this is a very dynamic way of handling messages. These class structures can be changed at runtime. In particular, using the NSBundle class makes it relatively easy to add classes and methods to your program while it is running. This very powerful technique has been used to create applications that can be extended by other developers.
Challenge
Use NSDateFormatter’s setDateFormat: to customize the format string on the date objects in your LotteryEntry class.
Chapter 4. Memory Management
Let’s say that two instances of Person each have a favoriteColor that is a pointer to a color object. If two people have the same favoriteColor, the objects will have pointers to the same color object. As the people age, their favorite color might change. Eventually, the color object might be no one’s favorite (Figure 4.1).
Figure 4.1. The Problem
We do not want this orphaned color to be taking up room in the memory of our program. We want the memory deallocated so that we can put new objects in that memory, but we must be sure that the color is not deallocated while any objects are pointing to it.
This is a relatively tricky problem. Apple has come up with three solutions:
1. The first is manual reference counting, or retain counts: Every object has a retain count, which should represent the number of other objects that have pointers to it. If the color is the favorite of two people, the retain count of that color should be 2. When the retain count of an object goes to zero, it is deallocated.
2. Then, in Mac OS 10.5, Apple introduced garbage collection for Objective-C. The garbage collector babysits the entire object graph, looking for objects that can’t be reached from the variables that are in scope. The unreachable objects are automatically deallocated.
3. The new solution, introduced in Mac OS 10.7 and iOS 5, is automatic reference counting, more commonly known as ARC. ARC relies on the original retain-count mechanism but with a twist: The compiler manages the bookkeeping of retain counts for you.
What are the trade-offs? Manual reference counting is, after all, manual and requires some work on your part: You need to explicitly retain objects that you want to keep around and explicity release them when you are no longer interested in them. If not used carefully, the retain-count mechanism allows for a dastardly problem: Object A retains Object B, B retains A. Together, they are an island of memory that will never go away, because they are retaining each other. This is known as a retain cycle. Figure 4.2 is an example of a common form that retain cycles take.
Figure 4.2. An Island of Garbage
The garbage collector sounds good on the surface but has a performance cost: It requires CPU time to scan through the objects, looking for garbage. This can sometimes result in poorer or uneven performance. For example, in an application that requires smooth performance, such as an action game, or an application that plays back video being rendered in real time, the garbage collector can cause hiccups in the processing while it is doing a scan. Additionally, the garbage collector cannot manage memory that you allocate manually, such as with malloc(), without special treatment. Garbage-collected code cannot run on versions of Mac OS X prior to 10.5, nor will it be portable to iOS, which does not support garbage collection (likely for the performance reasons discussed earlier).
ARC provides the best of both worlds: You get the speed and efficiency of manual reference counting, along with the freedom from memory-management concerns that garbage collection allows. ARC isn’t perfect, however. It doesn’t magically fix the problem of retain cycles and, like garbage collection, doesn’t manage manually allocated memory.
ARC is enabled by default in Xcode’s project templates. Although we’ll take advantage of ARC for the rest of this book, we’ll pretend for most of this chapter that ARC doesn’t exist, so we can learn how retain counts work. It’s important to have a firm grasp