There have been a number of threads where people have run into problems with DrinkMixer as written in Head First iPhone Development when using iOS 4.0 or newer. There are two underlying issues causing the problems
- iOS4 introduces multitasking which changes the way applications “terminate” (in general, they don’t anymore).
- There’s a typo in the book (and corresponding code) that writes the modified drink list to the wrong file.
Let’s fix #2 first: On page 283 in the book you’re given a code snippet that writes the drink array to DrinkDirections.plist. Unfortunately, earlier in the book on page 173 we asked you to name the dictionary plist DrinksDirections.plist (note the ‘s’). So to fix this issue you need to change the code snippet on page 283 to save out the modified list to DrinksDirections.plist. That gets you halfway there
The next piece of the problem is an unfortunate side effect of the platform moving on. With iOS4 Apple has introduced multitasking support into the operating system. This means that applications typically don’t follow the same app lifecycle that they did in 3.x
With iOS4, applications don’t terminate when the home button is pressed. Instead, they are moved to the background and are in a backgrounded (suspended) state. These suspended applications can be killed off by the OS as necessary for it to free up resources and the application isn’t told when or if this happens. In short, most of the time our DrinkMixer application will never receive the UIApplicationWillTerminateNotification, which is what we use to trigger saving the modified plist
With iOS4 there is a slightly different application lifecycle pattern you should use for your apps. Instead of responding to termination notifications (and the applicationWillTerminate: selector in the AppDelegate) you should save data when your application is backgrounded (or even more frequently if possible, see the iPhone Development Guide for suggestions here). You can do this in your app delegate in the “applicationDidEnterBackground” method or you can register for the UIApplicationDidEnterBackgroundNotification if you want other parts of your application to know when your app has been backgrounded. That’s what we need to do here
Fortunately, the change is simple. Instead of registering for UIApplicationWillTerminateNotfication as described on page 283 you need to register for the UIApplicationDidEnterBackgroundNotification. So, the code in the first block on page 284 should read
// Register for application backgrounding information so we can save data [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationDidEnterBackgroundNotification object:nil]
Hopefully this will sort out the issues people have been seeing with DrinkMixer and we’re working on updating the code and book to be 4.x compliant in the near future. Sorry for the frustration and I hope this helps – Dan