Friday, June 11, 2010

Multitasking on the iPhone

With iPhone SDK for iOS 4, fast app switching is the crux of multitasking. Fast app switching is when the application's state is preserved, and can immediately resume when the application becomes active. Although it is enabled by default, it requires tight integration with the multitasking UI.

There are four states in fast app switching: active, inactive, running, and suspended. Suppose you have Maps open on your iPhone. When you press the home button, your application's state is preserved and the applicationWillResignActive callback is sent to the delegate, telling the delegate that your application is now becoming inactive. Once the application has become inactive, an applicationDidEnterBackground callback is sent to the delegate, telling the delegate that your application is now entering the background. Shortly thereafter, the application moves into a suspended state, and no indication is given to the delegate in this case. Now suppose you hit the Maps icon again, at that point your Maps application comes out of the suspended state, enters the active state (applicationWillEnterForeground), and at last enters the running state (applicationDidBecomeActive). If for some reason, the application fails to preserve state and suspend itself, or if the application fails to launch, an applicationWillTerminate callback is sent to the delegate.

iOS also supports background execution for task finishing (extra time to complete a task), audio (play music), location (use GPS), and VoIP (make and receive calls). To use background execution for those four items, you'll need an explicit declaration in your app's info plist.

Here is a list of responsibilities and best practices when multitasking on the iPhone:
  • Save the app state incrementally.

  • Reduce memory usage and flush caches of data that can be regenerated: The system terminates apps when the memory exhausted. Using less memory allows more apps to remain alive, and increases the chance of your app staying alive. You'll want to reduce memory in the applicationDidEnterBackground callback.

  • Free backing graphic stores: Views and layers are backed by backing stores and view controllers. Of course, there is a trade off between recreating views and memory savings. When deemed appropriate, release non-visible UIViewController views, and flush [UIImage ImageNamed] cache. Release images [myImage release];
  • ImageNamed cache will repopulate lazily as images are requested during app state restore.
  • Do NOT use the GPU: It is off limits in the background. For example, creating an EAGLContext or issuing OpenGL commands will result in termination. When you enter the background, stop your GPU usage (stop using OpenGL altogether).

  • Consider memory mapping: Read-only memory can be reclaimed without terminating the app.

  • Pause your app when appropriate, and update the UI to show the change. This is typically performed in applicationDidResignActive.

  • Remove alerts and actionsheets if appropriate (via code)
  • Prepare for the application screenshot: The system takes a screenshot of your application. It is used when your application is animating back to the running state. You'll want to hide sensitive information and stop animations before the screenshot is taken.
  • System change notifications are not delivered to suspended applications. The notifications will coalesce into a notification queue. When the app is resume, then all the notifications will be delivered all at once. Therefore, prepare your app to handle bursts of notifications. Avoid delaying app responsiveness, and avoid rapid UI updates.
  • Handle errors and reestablish connections: When the suspended application resumes, the application must be prepared for lost network connections.
  • Holding exclusive access to shared data while suspended is not allowed. It results in termination, and is enforced upon entry to the suspended state.

For more information, consult the iPhone OS Programming Guide.

My source of knowledge: WWDC 2010 session on adopting multitasking on the iPhone

    No comments: