iPad Multitasking and You


Any iPad app now needs to consider how they will be used on iOS 9. The new system multitasking capabilities will greatly improve users’ ability to do more with their iPad, with less severe context switching when using multiple apps at once. Our users already use more than one app at once, making use of the app switcher, but beyond handling backgrounding well we’ve not had to do much about it as developers before. That’s all changed.

Styles

There are three styles of multitasking made available with iOS 9, Slide Over, Picture in Picture, and Split View.

Slide Over lets the user bring a panel in from the right hand side of the iPad, and choose a secondary app to display there. Only apps which adopt multitasking are available in the picker, and only the Slide Over app is in the foreground. There’s no change in size class or layout for the disabled primary app, however the secondary app is displayed in a compact size class, so this is the crucial experience to consider here.

Split View lets the user drop a Slide Over into a joint foreground view with the primary app. Both apps are in the foreground, both can recieve touch events (even simultaneously), and the apps available space can be resized between two snapping positions. Either app can also be given back the full screen by pulling the divider to one side of the screen or the other. Most of the positions for the divider lead to both apps having a compact size class.

Picture in Picture can be active over another app, or over two apps in Split View or Slide Over modes.

Support

iPad Air, Air 2, Mini 2 and Mini 3 all support new multitasking APIs. All of them support Slide Over and Picture in Picture, while only the Air 2 supports full side-by-side app use in Split View (not to be confused with the existing single app UISplitViewController.) That limitation is likely due to the Air 2 having double the RAM of the other models, 2GB, but it’s likely that this year’s crop will all support the full slate of multitasking modes.

Adoption

It is possible to opt out of the multitasking APIs. It seems like almost no apps should do this - Apple have stopped short of requiring it as an App Review guideline, but this is what they have to say on the matter:

Most apps should adopt Slide Over and Split View. From a customer’s perspective, an iOS 9 app that doesn’t adopt Slide Over and Split View feels out of place.

Consider opting out only if your app falls into one of these narrow categories:

  • Camera-centric apps, where using the entire screen for preview and capturing a moment quickly is your primary feature
  • Full-device apps, such as games that use iPad sensors as part of their core gameplay

Otherwise, Apple, and your customers, expect you to adopt Slide Over and Split View.

Apple - Adopting Multitasking Enhancements on iPad

It’s also all or nothing - you can’t opt to support Slide Over but not Split View.

Layout

Apple keep telling us that these APIs are easy to adopt, that you can make the changes in minutes, that it’s not much work for developers. That’s very true, if you have already made the changes they’ve pushed for the last couple of years, particularly regarding Size Classes, Adaptive Layout, and Auto Layout. For the rest of us, it’s going to be a lot of work, and there’s no getting around it.

A lot of the older APIs used for layout are now unusable, as the device’s state and the app interface’s state are decoupled. For example, UI_USER_INTERFACE_IDIOM will always return iPhone or iPad correctly for the device the app is running on. That makes sense, but if you rely on it for almost anything it will have to change, as it’s likely that you’ll want to display the old iPhone interface as the secondary app in Slide Over or when in a compact Split View.

Orientation is a no-go, as both of the APIs for that are device bound. Yes, even UIInterfaceOrientation, as that refers to the Status Bar, not the active app. To handle these changes, our apps need to respond to Size Class changes (willTransitionToTraitCollection:withTransitionCoordinator) and just plain size changes, as size class doesn’t usually change for an orientation change (viewWillTransitionToSize:withTransitionCoordinator).

Both orientation and multitasking layout changes can be made using those methods, so by implementing changes of size, we can reduce the complexity for each of those scenarios. UIPresentationController can be used to make the right decisions for presentation style at different points, for example when a modal view should be presented in a popover, or as a full screen, or as a form sheet.

Our app should be able to change size at any time, as the user or the system can trigger these changes whenever, even when we’re in the background. It does this, for example, to take screenshots for display in the various multitasking views, or while the app is waking up.

UIKit has some changes to be aware of:

  • UIScreen.bounds returns the screen’s bounds, which is not neccesarily our app’s bounds - use UIWindow.bounds
  • UIWindow.frame.origin is always (0, 0) no matter where our app is presented
  • The new ReadableContentGuide can be used to keep long-form text within sensible margins for the current size class.

Resources

System resources are shared between apps. This is particularly critical when the app is used in Split View, as both primary apps get an equal right to the system’s memory and CPU cycles. If apps take too long to respond to user interaction (16ms to maintain 60fps) the UI will start to stutter. Worse, if the system runs out of memory, the active apps will be terminated and the user dropped back to the home screen.

Even if you opt out of the multitasking APIs, your app needs to handle this - it’s not possible to prevent users opening another app in the foreground in Slide Over, which will increase memory pressure and CPU contention, and if it’s not handled correctly, the apps will be terminated.

Profiling your app’s resource use just became a critical part of testing. On the iPad Air 2, there’s the potential for three apps to be using system resources at once, and on the other models two could be in contest for the limited RAM and CPU available (though the PiP app is running in the background.)

Apple have developed and clarified their APIs for memory management and reacting to a memory-constrained device, and it’s possible to make your app a really good citizen by marking memory in use as purgable when its contents can be recreated, or even directly memory mapping to disk when you need to access a large amount of read-only data. NSCache is also a great time saver in this regard, as it automatically responds to memory warnings for us. See the WWDC15 video Optimising for Multitasking on iPad for iOS 9 for a really great run down on the options available.

Apple recommend in that session that we take time to define our memory ‘working set’ - what is needed to run well and transition well, and nothing more. Once that’s known, it’s possible to mark nice-to-have memory as purgable ahead of the system becoming memory-constrained, so that the system can reclaim it quickly. This is much better than simply implementing the low memory methods, as the system may need memory more quickly than it can wake up our app and run those methods - if that’s the case, our app will just be terminated unless the system can directly take memory from us.

CPU contention is less catastrophic, for the most part, as it tends to result in a stuttering UI rather than the app being terminated. The exception to this is blocking the main thread; if we do that for too long in the multitasking environment, the app could be terminated. Quality of Service bands can be used to classify CPU-bound work to see that it’s scheduled appropriately according to its urgency and importance.

Summary

iPad multitasking is coming, and users will expect it to work. To make that happen, we need to closely evaluate our apps and ensure that they are good citizens and up to date in their use of system APIs. There’s a lot to be done, but it should be well invested for the app as a whole, and to improve the code base. If we had to do all this work just to support a small set of users, and not get any other benefits, it would be an opportunity lost and probably just mean we are storeing up more problems for the future.