Getting Started with Multitasking on iPad in iOS 9

Session 205 WWDC 2015

iOS 9 on iPad introduces the ability to view and interact with more than one app at a time. Discover how to update your code to take advantage of enhancements to multitasking and how to participate in Slide Over and Split View. Learn specifics about how to architect your app and understand best practices for adapting to a dynamically sized interface.

[Applause]

Peter Hajas: I am so excited to be here today to talk to you about multitasking on iPad.

My name is Peter Hajas, I'm a UIKit Frameworks Engineer, and later on I'll be joined by my colleagues, Jacob Xiao and Kurt Revis.

So you can see that even UIKit is multitasking for this talk.

Multitasking is a giant feature, and so we have split it among three talks, of which this is the first.

Tomorrow afternoon you can hear all about the great new media enhancements that we have brought to iPad and iOS 9, and learn about picture-in-picture video and how your app can use the camera alongside other apps in multitasking.

Later that same day is a really great talk about how your app can be a great citizen alongside other apps that are multitasking on iPad.

I really encourage you to check out both of these talks tomorrow.

Today we're going to go over three topics.

The first, multitasking in your app: what is it, why should you adopt it, how you can adopt it, and what does it mean at the UIKit level?

The second is changes that we have made to UIKit to make your multitasking adoption experience really easy.

And the third is making the most of the latest and greatest UIKit APIs to make sure your app really shines in multitasking.

Let's get started.

As you saw in the keynote, multitasking brings a great new experience to users on iPad.

They can be doing one of their favorite things, like browsing the web, and slide in from the right to interact with another app.

We call this mode 'slide over.' The user can then tap the divider to the left of the slide over tap to pin the apps side by side.

As you saw on the keynote, we call this mode 'split view.' Being that you're all iOS developers I'm sure that you're really familiar with our UISplitview Controller API.

And I can assure you that that's completely different from split view.

[Laughter]

Peter Hajas: The user can grab the divider between the two applications and resize them for a 50/50 split view UI.

They can then take the divider and keep dragging to the left to promote the side app, in this case, Maps, to be full screen.

Then they may choose to slide in another app, or the same one, again from the side.

With multitasking on iPad in iOS 9 the user is in control of the experience, the apps that are running, and the sizes that those apps are running at.

There is another really cool feature of multitasking in iOS 9 on iPad, and that's picture-in-picture video, which you can hear all about at tomorrow's media multitasking talk.

Today we'll be covering how your applications can adopt split view and slide over.

In order to understand how to adopt those, it is important that we talk about something that's become increasingly important in UIKit apps and that's adaptivity.

In the past, we have encouraged you to make your applications universal.

This means the same app can run on the iPhone and on the iPad.

Last year we introduced a simplified way for you to do the check for what type of interface you should be providing to your user, through the introduction of the horizontal size class.

Last year, iPhones in portrait have the compact horizontal size class.

They traditionally display, for example, a single column of content, whereas iPads have the regular horizontal size class.

Many of Apple's own system apps use this to indicate that they should show multiple columns of content and change the information architecture that they present to the user.

Also with the devices at last year's Worldwide Developer Conference, this held true while the devices were held in landscape, compact horizontal for the iPhone, and regular horizontal for the iPad.

So that was last year's Worldwide Developer Conference.

But if you look closely, there was another message last year that's really obvious if you use a microscope; we were telling you to get ready for the iPhone 6+.

Like our existing iPhones, the iPhone 6+ has a compact horizontal size class.

But when rotated into landscape, it has the regular horizontal size class.

This is the first time that an app can have different size classes while it's running.

And that brings us to this year.

Similarly, if you take this year's invitation and draw the lines and rotate it where you know it logically makes sense, it forms a P, the P of iPad multitasking; it is obvious.

[Laughter]

Thank you.

So how does iPad multitasking work with adaptivity?

Let's take an example of a slide over app.

The user slides over from the right side of the display and the app comes up in a compact horizontal size class.

It shows what we would traditionally refer to as the iPhone experience.

Then the user may choose to resize their app to be full screen and then it will change into the regular horizontal size class and display its traditional iPad UI.

Two new things happened here that never have been possible before on iPad.

First, the app began its life as a compact horizontal size class, something that has never been possible on iPad before.

Second, the app changed size classes when the user resized it.

This is also brand new to iOS 9.

So what does this mean for your app and your users?

Let's look at it from those users' perspectives.

They could be browsing the web and want to interact with another one of their favorite apps on iPad.

So they'll slide in from the right and they'll want to see your app in this list.

By adopting multitasking in your app on iPad and iOS 9, you will let users get into your app more, spend more time in your app while they use it alongside their other favorite apps on iPad, and use your app in brand-new ways that you may have never imagined in concert with their other apps.

Users will expect that all apps on their iPad support multitasking, and we're here to help you adopt it.

Let's go through just how easy it is to add multitasking to your iOS app.

I have got great news for you: it is really easy.

All you have to do is use the Xcode 7 beta and create a new project.

All new projects created in Xcode 7 have iPad multitasking enabled by default, and all the code you write will be running in multitasking, and that's it.

Just make a new project.

[Laughter]

Peter Hajas: Now, right before this talk, off stage, some of my colleagues reminded me that there are one or two existing apps that may choose to adopt multitasking.

And for those apps, it is easy also.

You just need to follow three simple steps.

First, build your app with the iOS 9 SDK.

You can do so in the build settings of your Xcode project.

Second, support all orientations in the iPad version of your app.

At last year's conference, we encouraged you to think of orientation changes as simple bounds size changes.

And this advice continues with iOS 9, because a multitasking resize is just that, a bounds size change.

But because the user is in control of what orientation they're holding their iPad in, in multitasking it is important that your iPad app supports all orientations.

Finally, the third thing you'll need to do is use Launch Storyboards.

Introduced last year, Launch Storyboards are a great way for you to specify one storyboard as the launch appearance for your app in all sizes, configurations, orientations, and devices that iOS supports.

With all the different sizes supported by iPad multitasking, using Launch Storyboards is a requirement for adding it.

One important note here if your app requires a full-screen experience, you can opt out by using the UI Requires Fullscreen key in your info.plist.

Now that we've gone over just how easy it is to create a new project with multitasking or add it to your existing project, let's go through how it works in your app at the UIKit level.

There are some very important changes that you should be aware of.

In the past, UIScreen Bounds has returned the visible bounds of the entire display of the device.

And this continues in iOS 9.

Whether your app is running in full screen or is resized for multitasking, one really important change is that UI Window Bounds, well, it returns your window's bounds.

But your window's bounds will no longer always be the same as the screen bounds of the device, for example, when your app is resized in multitasking.

Another important change is that your window's frame origin is always in the top left, (0,0), whether you're running on the left side of the screen or on the right side.

We don't want you to have to worry about which side of the screen you're on or what other apps you might be running next to.

We only want you to focus on the experience in your app.

Now let's talk about the different types of transitions that can take place when your app is being resized.

We'll use an example, an app that's great with multitasking in iOS 9, the brand-new Notes app.

This is the new Notes app running as a slide over app on iPad.

You will notice that it looks a lot like the Notes app on iPhone.

It shows a single column of UI.

We call this the horizontally compact size class.

Later on, the user may resize our app and at a certain point we'll change what class of experience we should be providing to the user.

Notice that Notes now displays two columns of content.

This is that same horizontally regular size class that we saw earlier.

Notice how Notes has changed the information architecture of the app to show your notes list on the left and a note on the right.

This is the type of change that you should use size class transitions to influence.

One important thing to note about these transitions is that not all resizes will trigger a size class change.

For example, if Notes is running in split view on iPad and the user resizes the app a little bit, it won't change size classes.

It still shows a single column of UI.

Instead of changing the experience class, Notes uses this new size to influence its view's positioning and layout.

Look again as we make the app a little bit smaller.

Still a single column of UI.

UIKit has made some important changes to our current API to make this really easy for your app to adopt.

One of these technologies that we encourage you to use is Auto Layout, UIKit and AppKit's declarative view layout system.

Auto Layout allows you to position your views using constraints, and then when bounds changes, Auto Layout will reset their centers and frames appropriately.

It is really easy to use.

New in iOS 9, we have added some great new constraint convenience API that makes it really easy to create Auto Layout constraints.

Also if you use the leading and trailing layout attributes, you'll get a lot of the right-to-left language support for free in your app.

Another area of importance that we saw for helping apps handle resizing is in the form of legibility.

We're introducing a new API on UIView, 'readable content guide.' This will return a UI layout guide, which represents the legible region in a UIView.

This means that if you use this readable content guide to position your views, they will always be at a legible width.

For example, in this sample app, which uses readable content guide, the view is full size, it is the size of the whole iPad.

But the readable content guide has given it some generous margins to make sure that the lines are really easy to read.

A great feature of using readable content guide is it will automatically adjust depending on what size and device the app is running on.

It also works great with dynamic type, something that we encourage all apps to adopt.

You can also use it with or without Auto Layout.

A common component in many iOS apps is UI Table View.

And we wanted to make legibility really easy there too.

So we have introduced a new property on UITableView, 'cell layout margins follow readable width.' When this property is set to yes, your table view's cells' content view will have layout margins set such that content laid out relative to those margins is at a comfortable, legible width for the user.

This means that by simply using the layout margins in your UITableView cells' content view, the contents in your cells will be at a comfortable width whether running in full screen on iPad or in a smaller screen such as an iPhone in portrait.

Now that we have talked about some of the great improvements for multitasking, I would like to hand it off to my friend and colleague, Jacob Xiao, who is going to talk about what's changed in UIKit and some best practices for your apps to follow.

Jacob?

[Applause]

Jacob Xiao: Thanks, Peter.

I would like to tell you some of the changes to iOS to support multitasking, and also some best practices for working with those changes in your apps.

So, last year, we asked to you make your apps adaptive by using traits and size classes.

And you can see more information about that in the "Building Adaptive Apps with UIKit" talk from last year.

So now that iPad multitasking is here, what has changed?

Well, the answer is not much.

That's all for us.

Enjoy the conference.

[Laughter]

Jacob Xiao: Okay, so, there are a few important changes that you want to keep in mind to give your app a great experience with multitasking.

And let's talk about a few of those.

Let's start with orientation.

How many of you have code in your app that looks something like this?

It is okay.

This is a judgment-free zone.

This kind of code made a lot of sense in the past, to give your app a different layout when it was in portrait or landscape, to really make the best use of the space that was available to you.

But you want to think about how that should work with iPad multitasking.

For example, here, although the iPad itself is in landscape, we don't really want to use the landscape version of our layout here, because we have so much more vertical space.

It makes a lot more sense to use the previous layout that we would have called the portrait layout.

So with multitasking it is better to avoid thinking about things in terms of the interface orientation specifically.

Let's take a look at what you can use instead for these kinds of changes.

To get a better idea of this, let's take a closer look at what happens during rotation.

First let's take a look at an iPhone rotation.

As the device rotates, your app is resized and rotates along with it.

But we can actually break apart this transition into two changes that make it up.

First, your app is resized to be the new content size, and then it is actually rotated to face where the user is looking.

Now we can do something similar with rotation on iPad including with multitasking.

Once again, this is what the rotation itself looks like, and we can break it apart into first, that content resize, and then, the rotation.

Now, when the user is actually viewing this rotation, these two changes happen at the same time.

But it is useful to think about them as two independent changes.

And one of the great things about doing that is that you can really share a lot with multitasking resizes.

Here the same kind of thing is happening, but just the resize portion, not the rotation.

So as the user resizes your app, it is just a content bounds size change.

So, in the past, if you were using the interface orientation explicitly, I would encourage you instead to think about how you want to deal in terms of the view size changing for these kinds of layout changes.

Another good option to consider is the vertical or horizontal size class, and by using either of these approaches your app will work great with multitasking.

So next, let's take a closer look at transitions like rotation and multitasking resizes.

Previously we had callbacks for your app related to rotation.

But these callbacks work specifically in terms of the interface orientation changing.

So instead, in iOS 8, we introduced new callbacks related to the trait collection or the view size changing, and we strongly encourage you to use these instead.

Now, to get a better idea about how this kind of rotation transitions happen, let's take a look at a timeline of one of those transitions.

Let's start with rotation.

Now we can divide this rotation transition into a few different stages.

First, we'll set up for the change that's about to occur.

Then, we'll create the animations we'll be showing to the user.

And then we'll actually run those animations.

And this stage is the part that the user actually sees as the rotation happened.

Then, when everything is done, we'll perform some clean up.

Now the point during this transition where the size and size classes actually change for your app, is just at the end of the 'setup' stage.

So now that we have seen the different stages of this transition, let's see how those callbacks fit in.

Both of the transition callbacks happen as part of the 'setup' stage of these transitions.

Now, similarly, as the size class is changing, the 'trait collection did change' method is called on your views and view controllers.

Now the two transition callbacks will not only give you information about the change that's about to occur, they also pass your app a transition coordinator.

And transition coordinators have great API that you can use to add your own alongside animation blocks to be run as part of the main animation.

And if you do those, they'll be set up during the 'create animations' stage.

Similarly, if you add completion blocks to the transition coordinator, those'll be run at the end, as part of the 'cleanup' stage.

Now, notice that there aren't any callbacks to your app during the 'run animations' stage specifically.

And that's because it is generally better to perform the work that you want to do either at the very beginning or the very end of these transitions.

So now that we have seen the rotation transition and the timeline for what happens, let's take a look at a multitasking resize.

Now, during this transition, we first perform some setup, then we create some animations well, hopefully you see the pattern here.

These are the exact same stages, and the callbacks happen in the exact same way with multitasking resizes.

And that's what's really great about these new callbacks.

They allow you to use the same code between rotation and multitasking resizes.

Now, there is one important thing to keep in mind specifically about resize transitions.

And that's that your app has only a limited amount of time to perform the changes that it wants to do.

Just like with app start up, if your app takes too long to make these changes, then it will be terminated.

But I'm sure that won't happen to any of you.

So, one important thing to keep in mind, if you're implementing both of these to your transition callbacks, is that 'will transition to trait collection' will be called before 'view will transition to size.' And this is useful to keep in mind.

However, as Peter mentioned earlier, there are some multitasking resizes where only the size will change in your app and the size class will stay the same.

When this happens, the trait collections don't change, and so we won't call the trait collection change callback methods, we'll only call 'view will transition to size.' You can still use the transition coordinator APIs to add alongside animation and completion blocks.

Now, similarly, there are some cases where only the trait collection of your app will change, but the size will stay the same.

This can happen, for example, when you're overwriting the trait collection of a view controller.

So as you're implementing these callbacks, make sure that you don't assume that just because one of them is called, the others will be called as well.

And that's transitions.

Next, let's take a look at windows and specifically UIWindow.

Generally, when your app starts up, you'll create a new UIWindow and give it a frame that's equal to the bounds of your main UI screen.

Now, when that happens, if the user resizes your app during multitasking, then that UI window's frame will automatically be resized to match the new size of your app.

And that will continue as long as the user is resizing your app.

However, if you create a UIWindow that has a size that's different from the screen's bounds, then we'll leave that window to have the same size as your app is resized.

As Peter mentioned, the origin of UI windows is in the top left of your app even as they're resized.

So all of these UIWindows will move along with the rest of your app.

Now, generally, in the past, to make a full-screen sized window, you would create the UIWindow and explicitly give it a frame that was equal to the main UI screen's bounds.

And you can still do that with iPad multitasking, but in iOS 9 we've made this even easier.

Now you can just create a new UIWindow without passing any explicit frame, and we'll make it the correct size that your app is using right now, and automatically resize it along with all multitasking resizes.

Okay. Now let's take a look at presentations.

In iOS 8, we introduced UI Presentation Controller.

And this is a great class for making custom presentations or for working with system-provided presentations.

And you can see "A Look Inside Presentation Controllers," a talk from last year's WWDC, for more information about using this class.

One of the great things about presentation controllers with multitasking is their support for adaptivity.

So, for example, you can show a popover presentation on an iPad, and when your app size class changes, in this case to the compact horizontal size class, it will automatically transform that presentation into a style that makes sense.

So, here, we have adapted to a modal full screen style.

And this happens between devices as well.

For example, if you perform that same popover presentation on an iPhone, it will automatically show it as a modal full screen presentation there as well.

On an iPhone 6+ in landscape, we'll also make that presentation a form sheet presentation for you.

And all of these changes happen automatically in your app just by using 'view controller presentations.' However, you may want to interact with how these changes occur as well.

For example, in this app, as we're showing a popover presentation when we're in the modal full screen style, we'll want to show a "Done" button inside of a navigation bar so that the user can dismiss this presentation.

But when we're using the native popover presentation style, we don't need to show that "Done" button, since the user can just tap anywhere outside of the popover to dismiss it.

And we can make these kinds of changes with the 'adaptive presentation controller delegate' API.

In fact, we introduced some new methods to this protocol in iOS 8.3.

These methods allow you a lot of control over the changes that happen as your view controller presentation is adapted.

So you can do things like hide and show navigation bars or whatever other changes make sense for your app.

Now, one last thing to keep in mind specifically about popover presentations, it is to always make sure that the arrow from the popover points to the right source for that popover.

This is particularly important as your app is adapting between the horizontally compact and regular size classes.

You can easily do this with a popover presentation controller API.

Either set the barButtonItem or set the sourceView in sourceRect.

So that's presentations.

The last thing I'd like to tell you about is some changes to the keyboard with multitasking.

Now, when the user is multitasking with your app, if they tap on a text field, like the search bar in Maps, then the keyboard will actually be shown over top both apps that the user is interacting with.

And this means it is really important for you to consider whether you want to move pieces of your app out of the way of the keyboard so that the user can still interact with them.

You can do that by using the UIKeyboard Notification API, just as you had in the past.

You can use these notifications to make changes to your app like setting scroll views content insets or moving important UI elements to stay visible.

So, for example, in this app, we may want to move the comment field and the ratings view to still be visible by the user.

And this is a really important change because in the past the only time that your app would interact with the keyboard is when it had explicitly shown it itself.

But now, with multitasking, the other app that the user is using can cause the keyboard to appear.

So you'll want to consider whether any of the views in your app need to move pieces of their UI to stay visible as the keyboard is shown.

So those are some changes and best practices for iPad multitasking.

A few important things to remember are to consider size and size classes instead of orientation as your app is rotating.

And to think about how you shall want to respond to transitions like rotations and multitasking resizes.

And finally, to use adaptive presentations to make your app work great on all of our devices and all of the different contexts that it is used.

Now I would like to turn things over to Kurt to tell you how you can make the most out of multitasking.

[Applause]

Kurt Revis: Thank you.

Thank you, Jacob.

Thank you, Peter.

So now you know how and why your app can adopt multitasking.

You know what's changed not much.

You know what to do, what not to do.

So I'm here to tell you how your app can make the most out of multitasking and deliver a great experience to your users.

So really your app needs to be designed for adaptivity.

And I'll reiterate three things we talked about earlier.

First, your app should be universal; your app should run on iPhone and iPad.

Second, don't think of those user experiences as being iPhone and iPad anymore; think of them as being for compact and regular widths, because now that compact width experience can happen on the iPad.

And then last, use adaptivity to change between them when the user changes the size of your app.

So, the challenge when designing for adaptivity is making your app adapt to these dynamic size changes.

And I'll give you two things, actually six strategies that your app can adopt in order to make it flexible and make it handle dynamic size changes, and then I'll talk about some finer points that will come up, some things you will run into when you adopt multitasking and some guidelines of how to handle those things.

So let's get started.

The first strategy: be flexible.

Don't hard code sizes.

Don't make assumptions.

Your app should look at what size it is and do something based on that.

And it should also react to changes in its size.

So the only way to find out if your app is really flexible or not is really to try it out, try stretching.

So let's do a little exercise here, a little warm-up.

You will find there's a yoga mat under your seats in front of you, so please get that out!

No. Unfortunately, I'm only talking about your app.

But we'll do the same thing.

We'll take your app through a warm-up exercise.

We'll run through all the multitasking cases and we'll watch your app's UI carefully.

Take notes.

What works; what doesn't work?

When you're doing this, concentrate on the layout of what your views are, don't worry so much about the animations or anything like that, especially if you're doing it in the simulator, because the experience will be different on a real device.

So let's start.

Your app has adopted multitasking and you can start it by sliding over.

Then resize your app bigger.

That's a size change.

Make it bigger again.

It will be full screen, another size change.

Now Slide Over another app and press the button to use Split View.

Your app will get smaller.

Finally let's rotate the whole iPad, so we'll get a size change and the rotation will happen, the orientation will change, and that will be animated.

So these are all things that can happen to your app and you should try out every place everywhere in your app to make sure that it can handle these things.

When you try this, probably you'll find some things work, some things don't.

So for help on fixing the things that don't work, keep listening.

The second strategy: use Auto Layout.

This should be no surprise; this is the way to make your app's UI flexible.

All you have to do is provide views and constraints, the system will consider all those constraints and set your views' frames based on those.

So you don't have to hard code anything.

You can also use the margins and the guides that UIKit gives you to construct these constraints.

And also in iOS 9, there's new APIs to make this whole process much more convenient.

So, to find out more about that, see the two Auto Layout talks on Thursday; I guarantee you'll learn a lot.

So let's run through this example that we saw earlier.

We have excuse me.

We have this app showing some text, and it is using those readable margins.

Now, how this works is your view size is large, but the readable content guide is smaller.

We don't want your app to have to worry about thinking, 'This is an iPad.

It is big; it is wide.

I need to handle these margins differently.' You just use the guide and it will work automatically.

So here is how to do this in code.

First, make a label; we'll put our text inside of that.

Second, the label goes in some super view and we'll get the readable content guide from that super view.

Now we'll set up some constraints to make that label match that readable content guide.

So the constraints is an array, and the first one that we do is make the label's leading anchor, that's the leading side, equal to the readable content guide's leading anchor, the leading side.

This is, note note that this is using the new iOS 9 convenience API.

We do the same thing for the trailing anchor on both sides.

So now, that label's width will match the readable content guide's width.

Then all we have to do is activate those two constraints and Auto Layout does the rest.

We didn't have to do anything.

So I could have also done this in Xcode.

I could have set this up in my storyboard, which leads me to the next strategy: take advantage of the size class support in Xcode.

You can set up your UI to do different things in different size classes.

For instance, using interface builder when you're editing a storyboard or a XIB file, you can add or remove user constraints from different size classes, and you can also change the attributes of views like the font size.

You can also take advantage of asset catalogs to make different versions of images that are used in different size classes.

And note that this applies not only when you're initially loading your UI the first time, but also when dynamic size changes happen.

We remember all of this stuff behind the scenes and we'll apply these things when a size change happens.

So I'll give an example.

Here I've made this storyboard and I've set up a UI with two views.

There is an image and some text.

I put them side by side; I made the constraints to do this.

I'm working on the default UI for my app; that's using the 'any width' class.

I would like to make a version that's a little bit different for compact width class.

So what I do is I click that control, I change it to compact width.

I have got the same two views, but I changed my constraints around to make the layout different.

Now the image is on top, the text is on the bottom.

I did that by clicking that control at the bottom, changing it to compact, and you see there's blue telling me I'm in a different, more specialized mode.

Now I could at this point run my app and try resizing it and see what happens.

But the nice thing is I don't actually have to do that.

I can see a live preview inside of Xcode.

Just use the assistant pane in Xcode and you can bring up more than one preview at a time of your storyboard in different configurations.

So here I have got iPad one-third width, that's what happens when you Slide Over your app, that's using the compact layout.

At the same time I'm looking at iPad full screen, the other layout.

So you can make as many of these previews as you want, just press the "+" button in the corner, and choose any size of iPhone, any size of iPad multitasking configuration.

You can see them all at once and they're all live.

We can also use asset catalogs.

I'll show how that works.

Here I've got an asset catalog; I'm looking at one particular asset.

I'll set this thing up to be universal; it'll work on all devices.

And then I'll do much the same process as before, I'll set up two different versions of it.

One for any width, the default.

And one for compact width.

Now you see I have got those two images there, that's the two different versions.

I can drag in a large star to work for the any regular width configuration.

I drag in a smaller image to be the compact width.

So that's Xcode.

Now, you can also drop down and do this in texture, in code yourself, if you would like to.

Just take advantage of the adaptivity callbacks.

So here is how to do this.

If you are in a view controller, you would override 'will transition to trait collection.' We'll give you the new collection that we're going to change to.

Or you can override 'view will transition to size, and we'll give you the new size that we're going to transition to.

Now let's say I want my app to have different UI depending on the horizontal size class.

That's pretty normal.

How we'll do that is override 'will transition to trait collection.' And the first thing we should do is call 'super, let the system do what it would normally would do.

Then we'll add our code.

We'll look at the new collection's horizontal size class, and depending on what that is, we'll do something different.

So here is where you put your code in.

If it is compact, change your UI for a compact width.

If it's regular, change your UI for a regular width.

If it's unspecified, that means we're in the middle of setting things up or tearing them down, and just don't do anything.

Now let's say I have that similar change, but I want it to animate alongside other things, like the case when I rotated the iPad, I would like my change to animate alongside that rotation, at the same time.

Here is how.

We start out exactly the same way.

Override the same method; call super.

Then, instead of making the change directly, we'll provide a block and we'll put our changes inside of that block.

So, here we've got a block, called 'animation, and we'll put our code to change the UI inside of there.

Then pass that block to the coordinator's 'animate alongside transition' method.

It will take care of remembering that block and calling it at the right time, once the animation is set up.

And any changes you make inside that block will automatically get animated.

So that's how to do it at the low level, in code.

I'll talk about some of the high-level API that UIKit provides to you.

First, as Jacob mentioned earlier, there is adaptive presentation controllers.

Second, there is the classics UI Table View, UI Collection View.

These let you build up a larger UI out of small things like a single row or a single item in a collection.

Also new in iOS 9, there is UI Stack View.

This lets you take a list of views and put them in a vertical stack or a horizontal row, and set up some parameters on how they get laid out.

Again, to find out more about that, check out the first Auto Layout talk.

The last bit of high-level API is big enough it deserves its own number.

And that's UI Split View Controller.

We use this in a lot of our apps like Mail and Messages and Notes.

And if it makes sense for your app too, use it.

I'll give you Mail as an example.

Here we're looking at full screen iPad and you see that the app is divided into two parts.

And note that this isn't the same thing as split view multitasking where you're looking at two apps.

This is one app.

So, we have on one side a list of messages to look at.

You can pick one.

On the other side, we have a view that shows the details.

In this case it is a particular message.

So if your app can handle a configuration like that or works that way, we really highly recommend that you adopt Split View Controller, because it will do a lot of work for you in multitasking cases.

I'll show you that a little bit later.

But first, here is how you adopt it.

You make a UI Split View Controller in your app.

That's typically the root view controller, so the top level of your UI.

And it is a container view controller, so it has children.

We call these the primary and the secondary view controllers.

In Mail, these are a table view that contains that list of messages, and on the secondary side, a custom view showing a message.

In your app you fill these in.

You provide the view controllers.

UI Split View Controller is responsible for deciding where and when to show these two view controllers.

Going back to Mail, in full screen we have got lots of room; we can show both of these side by side.

What happens if the user switches to a different app and then slides Mail over in from the side?

In that case it is a compact width, there is less room, so the Split View Controller adapts to this.

It decides it will show the secondary view controller to start that mail message, and it also provides navigation controls to go back to the other list, the primary list.

Once the user picks one of those, they can go forward again to the secondary list.

So those view controllers are still independent; they didn't have to make any of these choices.

So the thing to note here is that these are the same exact two view controllers that we were looking at earlier.

The differences are, they're smaller, and we're navigating between them in a different way.

So if you want to try this out, you have already got the code on your computer, in fact.

Just make a new Xcode, in Xcode make a new iOS application, and use the 'master-detail application' template.

It is automatically set up with a storyboard that contains a Split View Controller and view controllers for each side.

You can build on this to make your own app or you can just use it as a test bed to play with Split View Controller and see what it can do.

So those are the 6 strategies I'll give you.

And please mix and match these however makes sense in your app.

You can take a look at our sample code to see all of them in action.

This is an app called 'Adaptive Photos.' You can search for it on the developer site.

Try it out in all sizes of iPhone and iPad and iPad multitasking and see what it can do.

So that's the strategies.

If you use these, your app will start resizing nicely; it will probably work pretty well.

But you will run into some new things that happen.

So once you adopt multitasking, these new things may be a little tricky.

I'll give you some guidelines on how to handle them.

The first guideline, most important, the user controls your app's size.

The user is always in control of how big things are.

So your app cannot prevent size changes from happening.

I know sometimes it is inconvenient but your app can't prevent it.

Also your app can't cause a size change.

You can't say, 'My app wants to be full screen now.' It doesn't work that way.

And we really do mean that size changes can happen at any time.

The user might choose to resize the apps any time.

It's just like pressing the Home button.

They can do that any time.

So how do we react to size changes?

Well, our guideline is keep the user oriented.

Don't let the user get lost.

I'll illustrate that with a concrete example of a real app.

I have got a To-Do List app.

It has got a bunch of items I need to check off.

And I have got them in three categories: home, work, and school.

Now I'll put on my designer hat and I'll choose to make some UIs for regular width and compact width.

In regular width, I think, 'Well, it makes sense to put these all in a scroll view.

We'll put them on top of each other.

We'll let the user scroll through them.' In compact width, I think, 'Well, let's just show one of these categories at a time, each on a separate page, and let the user scroll from page to page.

But only one is visible at a time.' So that's great.

I have got two UIs.

But now I need to think about how to change from one to the other.

Let's say I'm looking at School right now.

And the user resizes the app to be regular width.

What do I do?

Well, by default, if I just go and make a new scroll view, and put my stuff into it, it's probably going to be scrolled to the very top, at (0,0), and now School isn't visible anymore.

So the user might get lost.

We don't want to do that.

The app should choose and make a good decision and scroll so that the same thing is visible again.

So School is visible.

This doesn't happen automatically; your app needs to make this kind of decision.

Let's say the user keeps working with the app, they scroll down a little bit.

They write some code; they check that off.

Great. Wrote some code today.

And then they decide to resize the app to be compact.

What do we do?

You will see that all three categories are visible on the screen at the same time.

So we could make a case for any one of them to be visible.

But in this case it probably makes sense, since they last checked something off in Work, and they're still looking at it and they haven't controlled away, that we should choose to go to that page.

But again, that's a decision the app had to make.

And your app will have to make decisions just like this.

So to keep the user oriented, don't make abrupt changes when the size changes from one thing to another.

Try to keep the same things visible.

You might have to be smart in new ways.

You might have to do something like keep track of what the user most recently looked at or touched that you didn't have to do before.

And also it is especially important when you're going from large sizes to small sizes, because you can't show all of the stuff that you were showing before.

So speaking of resizing, here is another new thing that can happen with once your app has adopted multitasking.

Let's say your app becomes inactive; the user presses the Home button.

After that happens, your app's size may change.

The system might want to take a snapshot of your app in a different size.

When that happens, the same adaptivity methods as before will get called, but nothing will be visible, the user won't see any of this.

When it is done, the system will restore you back to the original size.

Now this can be a little tricky to deal with, but I'll give you some guidelines on how to handle it.

And I'll show you a concrete example.

I have got my app again.

I'm active; it is in compact width and I'm looking at that Work page.

Now the user presses the Home button.

And the system will take a snapshot right now.

Now, this is not a new thing; we have done this for a long time.

What's going to happen is the user takes that snapshot and then when the app comes back active, we'll first show that snapshot and then we'll fade into the live app as it is.

So remember this snapshot right here, we're purple, we're at Work.

Now, with multitasking, the system will resize us to regular and take a snapshot for its own purposes.

And now the system is going to resize us back to compact.

Now here is the point where the app has to make a decision.

And I'll show you what happens when we make a bad decision and then a good decision, and the ramifications of both.

Let's make the bad decision first.

We go back to compact, and my app decides, 'well, Home was at the top, so we'll show Home again.' The app stays inactive for a while; the user comes back and activates the app.

Then the system shows that snapshot again from Step 3.

Remember, we were at Work.

It's purple.

It's that same snapshot.

And now the system will crossfade from that into the live app, which is at Home.

So that looked bad.

It was a really ugly animation, and it didn't use do what the user wanted.

They were in one place, they left the app, they came back, it is somewhere else.

That's no good.

So what we should do, backing all the way up....

We're in regular width; the system is going to resize us back to compact.

We should resize we should change the app back to the state that it was in when we were inactivated.

And then going forward, user activates the app; system shows the snapshot; it is the same thing.

We fade into the live app, it is the same thing.

It is seamless.

So that's the way you want to handle things.

When the app is inactive, maintain the same appearance when the size changes.

You can do this by, when the app is deactivated, remember your size and state, remember what page you're on.

When you get a size change, and you're still inactive, and it is sizing back to that original size, then apply that state that you remembered, go back to that original page.

So we're down to the last two guidelines, and these will touch on some things that we'll talk about in the later multitasking talks, but first I need to introduce some terminology.

So, there is two apps running.

The primary app is the one that starts out in full screen; it is what you think of traditionally as the app that's running.

When you Slide Over another app we call that the secondary app.

Now no matter how you resize the apps, they keep this identity; they're always the same.

And normally we treat these apps exactly the same.

There really are not too many differences.

The differences come in when we're talking about resources that can't be shared easily across both apps.

One of those might be an external display.

If you plug in a TV to your iPad or use Airplane Mirroring with an Apple TV, you can show UI both on the iPad and that external display.

With multitasking only the primary app will see the external display, not the secondary not the secondary app.

So normally apps that use the external display will split their UI across the iPad and the external screen when a screen is activated, when the user plugs something in.

And they are expecting that.

They just plug something in and they expect something to happen.

There is a quirk with multitasking now though.

Let's say your app is the secondary app and the user quickly resizes it to become the primary app, once it is full screen.

When that happens, your app will get a notification that that screen is now available, the external display is now available.

And if your app chooses to immediately take its UI and split it across the iPad and the other screen, the user might not be expecting that, depending on your app.

So try that out in your app.

Make sure you do something that makes sense to the user.

The last guideline is about performance.

And, again, we have a whole talk on this, so I'll only touch on some high points.

As we said before, if your app doesn't react to a size change fast enough, it will get terminated.

So when the size changes, do as little work as you can get away with.

If you have anything slow to do, use the completion block and 'view will transition to size' or 'will transition to trait collection.' And also, in the animation block, don't do any extra layouts; don't call 'layout if needed.' The system is going to do a layout at the appropriate time, and take advantage of that.

Just call 'set needs layout' and let the layout happen, because layouts can be time consuming.

So that's the strategies; that's the guidelines.

Now you know a lot about how to make your app work great with multitasking.

Now you know how and why to adopt multitasking in your app.

You know that adaptivity has been around since iOS 8; it is not a big stretch what we're doing in iOS 9.

And you know how to deliver a great user experience.

You have the technology.

So your users want to use multitasking; let them have it.

For more information, check out our documentation, especially "Adopting Multitasking Enhancements on iPad."

Check out our sample code.

You can talk to tech support, the developer forums, DTS.

For general inquiries, talk to Curt Rothert, our Evangelist.

And if you have more questions, we have more sessions.

Again, if you want to find out about picture-in-picture or sharing the camera, go to "Multitasking Essentials for Media-Based Apps."

If you want to find out how to be a good citizen and share resources like CPU and memory across the apps, go to "Optimizing Your App for Multitasking."

Last, visit us in the "Cocoa Touch and Multitasking Lab."

We'll help you out with your app.

So thank you for coming.

Go forth and multitask.

Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US