View Controller Advancements in iOS 8

Session 214 WWDC 2014

View controllers are fundamental to creating apps on iOS. Learn about the enhancements made to view controllers in iOS 8 to improve the user experience in your apps. Dive into using and creating transition coordinators and find out about all-new additions to split view controllers and navigation controllers.

Good morning, everyone.

[ Applause ]

I'm glad you guys could make it.

My name is Bruce Nilo.

I'm one of the engineers on UIKit.

And we're going to be talking about all the new stuff that we've brought into UIKit for iOS 8.

In case no one's told you, it's a big release.

There's a lot of stuff.

And two weeks ago when I was thinking about what I was going to say, I said, "Piece of cake.

I'm just going to list all the new features.

I'm going to also list all the things that are going away.

And I'm done, right?"

Well, that's what I ended up with, and I realized I really needed to cut down on what I was going to talk about.

So this is where we ended up.

And I just want to point out, though, that there's a lot more than what I'm going to talk about.

One of the most important things that we're introducing in iOS 8, in case you haven't heard, is we are providing APIs that are more adaptive.

What this means is that your user interfaces can more easily respond to changes in size and other changes, as well.

UISplitViewController used to be a kind of a pretty simple class.

Well, it's grown up in iOS 8, and we're going to talk about some of the new features that UISplitViewController has to offer.

We're going to, while we're at it, show how it's really easy to hide bars in ways that you've probably seen in some of our own apps.

Then we're going to shift gears a little bit and talk about presentations.

Presentation controllers have been introduced and are part of a whole architectural revamping of how view controllers are presented and how you can create great custom presentations yourselves.

That gave us the opportunity, by the way, to redo popovers, as well.

And popovers have now become integrated with UIViewController presentations.

Finally we're going to talk-not finally-we're also going to talk about new a API that we introduced that builds upon transition coordinators, that also helps your applications adapt.

And, finally, there's a subtle but pretty important change in terms of the coordinate spaces that you've grown to love.

And we'll talk about that briefly when we wrap up.

So, you've probably seen this picture, or a variant of it, a few times.

Many hierarchical applications on a phone might structure themselves this way, inside of a navigation controller.

And there might be some detail that you would see when you hit the Back button.

And on an iPad, you might choose to structure it a little bit differently.

Again, this is all kind of familiar stuff.

But there's no particular reason why you shouldn't be able to do this on an iPhone, if it suited your application.

We're going to show how that's possible.

So prior to iOS 8, most of your application coarse-grained structure was determined by looking at the device type, and possibly the interface orientation, as well as the size in which your user interface was being presented.

In iOS 8, we've taken the first two and abstracted it a little bit into two new concepts called traits and trait collections.

Size is still available, but typically size is a finer grain type of layout operation that can be easily accommodated using technologies like Auto Layout.

We're going to talk a little bit more about the former.

We'll also address the latter a little bit.

So what is a "trait collection"?

A trait collection, simply put, is a set of traits.

Not too surprising.

On a phone, you might see the window of your application return a trait collection that has the following traits: two size classes, an idiom, and a display scale.

This typically is the way a phone's traits are structured.

One of the most important traits that we've introduced is size class.

And size class deals with, on a coarse level, the available space that your application has and can therefore make decisions about what its structure should be.

Let's look at that quickly.

Here we have kind of a cartoonish representation of an iPhone.

And typically, the vertical axis is going to have a regular size class, whereas the horizontal axis is going to have a compact size class.

If you rotate a phone, we say that the size classes are constrained in both the vertical and the horizontal dimensions.

Now, an iPad is a little bit more free.

It's regular in all of its dimensions, or it has regular size classes in all of its dimensions, and that holds true when you rotate it, as well.

But that's not the full story, because some view controllers, like split view controller, can determine that its children, in this case the primary child, which is on the left side, has a more constrained size class in either dimension.

For a split view controller, it constrains the horizontal size class.

So, a size class is all about informing your application of the available space in some coarse way that you can make decisions about how you would substantially alter the application's structure.

We have API on specific objects that vend trait collections.

And in these cases they have values for both the horizontal and the vertical size classes.

Now, I like to think about the trait collections that come back from these objects as defining a point in a trait space.

We've introduced a new protocol that a number of our objects conform to which is a trait environment.

And you'll see the hierarchy on the right is kind of a window hierarchy that starts from a screen and proceeds down all the way to the leaf view elements that you have.

All these objects conform to the trait environment protocol, which means you can ask them for a trait collection, and what you get back is going to be a point in a trait space where every single trait has a value.

And not all of these objects define those values directly.

So, for example, if you asked for the scale of a leaf, the scale trait of the leaf of a view, it might actually, the system might walk all the way up to the screen to get that.

But the trait collection that you get back will have a value for that scale.

Finally, you will notice that whenever a trait changes in a trait collection, your object, the appropriate object will get a traitCollectionDidChange just before that object is laid out, so you can respond to that.

So I kind of implied before that you can, that a view controller, such as a split view controller, can override the traits for a child.

How do you do this?

Well, we've introduced a couple of new methods on UIViewController which allow you to do precisely this.

SetOverrideTraitCollection can be used by a parent to indicate what the appropriate traits are for any one of its children.

The trait collection that you pass in, in this case, isn't a point in a trait space; it might just be a single trait value which is then overridden.

So what I wanted to do was, before I go into the rest of the talk, is I put together kind of a toy application, which is going to highlight some of the features that we're going to talk about today.

This is kind of my canonical little photo note-taking toy application.

What you see here is basically a pretty standard thing.

You see a navigation controller.

And I can hit the Back button with this Photos, and I get a list, which is a simple table view.

I can select things.

That's great.

What's interesting, is that this is actually a split view controller.

Notice when I rotate, I stay inside a navigation controller.

However, I can do something interesting.

You see there's a Split button on the bottom of this toolbar.

If I hit it, you can now see a little bit more clearly that this is, in fact, really a split view controller.

You'll also notice that when I-let's hide this.

I can tap and interact with the bars.

I can create, I can move that primary controller off-screen.

But one of the things we're going to show is how easy it is to hide the bars if I tap on a view controller.

I can also get that Safari look where the bars condense really easily.

Alright. Let's go back into a regular old navigation controller look, and let's hit this Note button.

The Note button is going to do a presentation.

This is a view controller presentation.

It takes advantage of a couple of new classes that I might mention as we go through the talk.

What's interesting is this is, in fact, a popover presentation.

Now, I'll get into that a little bit later because it certainly doesn't look like a popover presentation.

But if I do something special on this little toy app-well, it didn't quite do it that time.

Now you'll see that that same thing is, in fact, a popover.

And we'll go through that a little bit.

Finally, I wanted to talk about, a little bit about rotation.

And to do that, I'm going to present another view controller.

This time it's a collection view controller, which has a bunch of little thumbnail photos.

And if I were to rotate the device now, the normal collection view flow layout behavior would basically relay things out so that everything is oriented now in the horizontal direction.

However, if I wanted to change what happened when I rotated so that it did something more akin to this, there's some interesting things that we can do.

And this is a perfect example of when you would use some of the methods like willRotate, interface orientation, and so forth.

So we're going to talk about that a little bit, as well.

Alright, so enough of a taste of what we're going to talk about.

Let's go back to the presentation.

And let's talk about split view controller.

So as I kind of implied, split view controller is now available on the phone, as well as on the iPad, and it has this interesting new property.

It has a property of being collapsed or not collapsed.

Now, what does it mean for a split view controller to be collapsed or expanded?

Well, an expanded split view controller, it's kind of obvious, might look like this.

However, it's not just a question of the two children being visible.

So I'm highlighting the secondary view controller of this split view controller, and you're going to notice that there's a little button off to the left.

We call that the displayModeButtonItem.

When I click on that, I can expand out the split view controller.

And even though we're only looking at the secondary controller, that split view controller is still expanded.

It is not collapsed.

And the reason why that is is because it's possible to show the primary controller at the same time as the secondary controller.

On the other hand, this is a collapsed split view controller.

You'll notice that the displayModeButtonItem that was on the left side is gone.

You can no longer show the primary and secondary controllers together.

They've been collapsed, and you can now get to the primary controller by hitting the Back button, which is up on the top-left corner.

So that's kind of what the difference is between the split view controller in its collapsed state and its expanded state.

It's important to know that split view controller by default are collapsed when they're in horizontally compact containers.

So by default on a phone, if you use a split view controller, it's going to appear in this collapsed state.

So I've implied that you can enable the expanded state of a split view controller on the phone already.

How do you do that?

Well, it's actually quite simple and straightforward.

You probably know the answer already.

First of all, you're going to take your split view controller and you're going to embed it in a parent container view controller, as follows.

You're then going to call setOverrideTraitCollection.

And you're going to inform that child split view controller that it is now in a horizontally regular environment.

The second you do that, the split view controller morphs into its expanded or not collapsed state.

You'll notice that the displayModeButtonItem, which is titled Photos in the lower left corner, has now become enabled.

If I wanted to show both controllers together, side by side, I could click on that displayModeButtonItem.

But we've also introduced a property called preferredDisplayMode, which you can use programmatically.

If you set the preferredDisplayMode to the all visible value, it's the same as, the same behavior would occur as if you clicked on the displayModeButtonItem.

And you'll also notice the displayModeButtonItem morphs into this kind of diagonal double arrow.

These items, this display mode item and this behavior are all customizable.

And this is via delegate API that you can look at in the header files that I'm not going to have time to talk about today.

So to go over some of that API, preferredDisplayMode is an enumeration.

Enumerated values are automatic, hidden, visible, and overlay.

Automatic is the old behavior that you are familiar with on iPads.

Hidden and visible are explicit means by which you can control the layout of the split view controller so that the primary and secondary are side by side.

An overlay is an explicit way that you can have the primary kind of go over the top of the secondary.

The displayModeButtonItem is also accessible in this API, so you can ask the split view controller for it and put it in whatever bar you want.

Although I'm not going to say it explicitly, if you were to look in the header files of UISplitViewController, you would find that most of the API that used to be there is now deprecated and replaced by new API.

One thing that I'd like to say is that a lot of people have always wanted to control the split width, and we've made that really easy to do.

So there's a new method, a new property, preferredPrimary ColumnWidthFraction.

And if I were to set that to one-half, say, the split width changes.

The API that enables that is this.

You can set a minimum and maximum bound of the split width in terms of points.

You specify the split in terms of a fraction and you can read back the actual point value with the primary column width property.

So what have we learned here?

One is, is that split view controllers can be used on both the iPhone and the iPad.

This makes it easy to write code that is kind of agnostic about the platform that it's going to be deployed on.

If you have a certain type of application layout that makes sense in either a collapsed state or an expanded split view controller state based on the available space, create a split view controller and the split view controller will adapt accordingly.

Split view controllers are collapsed by default in horizontally compact environments.

The displayMode property controls the appearance of the primary or left child view controller.

And you can also now specify the split width.

So there are a lot of other API that we added to split view controller.

There's going to be a talk immediately following this one which talks about in more depth all of the new adaptive APIs that we've added to UIViewController and UISplitViewController that you can attend and get more information.

So let's talk about condensing bars.

It's all about available space and highlighting your content.

So we wanted to make it easy to do.

It's really easy now to hide your bars.

Just set the hideBarsOnTop property, and they're gone.

If you- [ Applause ]

So what about that gray, you know, kind of Safari-looking condensing bar behavior?

Well, we've added a property for that, too.

Just set it to YES; when you swipe, those bars condense.

[ Applause ]

So we've added a couple of other properties, as well.

You know, the bars can hide when you're in a vertically compact environment.

They might condense when the keyboard appears.

You can control this all programmatically with an animatable property called navigationBarCondensed.

Well, at least you can control the condensing behavior that way.

So, yeah, that's it for condensing bars.

Okay, now the easy stuff is all done.

Let's talk about presentation controllers.

We have revamped the presentation architecture for view controllers on iOS 8.

You might recall that in iOS 7 we allowed developers for the first time to customize what the presentation transitions looked like.

Let's go back and kind of talk about how that looked and how you did that.

So, first of all, what you would do is, the view controller that you wanted to present, you would set the presentation style to Custom.

You would also set a transitioning delegate on that presented, on that view controller to be presented.

And then you would just present the way you normally do.

You'd tell the presenting view controller presentViewController, at which point the system takes over.

UIKit will ask the transitioning delegate for the animation controller that is your object that is vended by the transitioning delegate that you've set.

At which point UIKit prepares this internal object which conforms to this context transitioning protocol to set up some information that you need to know in order to drive your custom transition.

The views that are participating in this custom presentation are accessed via this viewControllerForKey property.

And then there's frame information and all of that stuff.

Now this object is passed into another method that is generated by UIKit to your animation controller, animateTransition.

You do your animation, the presentation's complete, and the animation controller goes away, and everything's good.

Well, there were a couple of problems with that.

Let's look at the view hierarchy to see what those problems might have been.

So we have the presenting view controller's view.

When the animation controller's vended, we set up kind of the environment in which this transition animation is going to take place.

That's kind of the container view that the context, the transitioning context is pointing to that your animation controller accesses.

When we send the animateTransition message to the animation controller, it's the animation controller now that's groveling in the view hierarchy, adding special views, adding the presented view controller's view, and one of the neat things-it was a feature in iOS 7-is that we didn't remove the presenting view controller's view.

And so this is what it ended up with, and the animation controller went away.

Okay, so the first question that comes to mind is, what object owns all these other-these views that are lying around that just got added by that animation controller?

Well, there wasn't a good answer for that.

In fact, that ended up causing a tight coupling between the animation controllers that were doing a presentation and the animation controllers that were doing a dismissal.

Sometimes that was easy to manage.

Sometimes it caused problems.

It often caused problems when view controller presentations were being stacked on top of one another.

So let's look at what we do in iOS 8.

It's going to look pretty similar in the beginning.

You're going to set the presentation style, just like before.

You're going to set a transitioning delegate, just like before.

You're going to send a presentViewController message to the presenting view controller, just like before.

However, now the transitioning delegate has grown a couple of new methods.

You can now get then this new object called a presentation controller.

And now it is the presentation controller that's responsible for asking the transitioning delegate for the animation controller and, in fact, for driving the actual transition.

Now, there's a lot of neat things under the hood that are going on here, and there's going to be a whole talk tomorrow, I believe, about presentation controllers, in depth, and how we used the UIKit to introduce some new API, as well.

But for now, let's look at what's going on in the view hierarchy.

So now, you'll remember you have this view hierarchy that corresponds to this custom transition.

The presentation controller's still around, and it holds a reference to the container view, which is where the whole transition is happening.

It also holds a reference to this thing called a presented view.

Now I want to point out, the presented view is not necessarily the view of the view controller that's being presented.

Maybe I put a drop shadow around that view because that's what my custom presentation demanded.

In order to accommodate that, we had to augment the context transitioning protocol a little bit.

So we added this new method called viewForKey.

ViewControllerForKey still exists, but viewForKey may return a different view than the viewControllerForKey.

And so when you build a custom animation controller, you want to make sure that you use the viewForKey methods to figure out which views are actually participating in the animation.

A presentation controller can also add other types of views that are completely unknown to other types of presentation controllers, say, like a dimming view that it wants to put over the entire back of the presentation.

I mentioned that in iOS 7, by default the presenting view controller's view was left in the window hierarchy.

Well, presentation controllers have a very rich API, and if you build your own, you can specify properties such as shouldRemove, should the presentation view controller's view be removed or not.

And if you set it to YES, it will automatically get removed.

There's one other property which is, I'm raising here because I think anyone who builds a custom presentation controller needs to at least be aware of, which is the shouldPresentInFullscreen property.

What this means is that a presentation will effectively, its container will be in the window and its, and the frame of that container view will effectively be the bounds of the window.

If you implement a custom presentation controller and set that property to NO, your presentation will no longer adapt.

Now, I know that doesn't make quite a lot of sense yet, but we're going to go through some stuff and then it will become more clear.

So let's quickly talk about some of the API that has been added for presentation controllers.

One is that you'll notice that it appears, it conforms to the appearance container protocol, the trait environment protocol, and this new protocol which we'll talk about in a bit called content container.

We talked about the containerView properties and the presentedView method and these two other properties.

As I said, there's a whole bunch of methods and logic available for you to create fantastic new custom presentations.

But that's beyond the scope of this talk.

So armed with this new architecture, let's talk about some features that we've added.

First of all, all the old iPad-only presentations are now available on the iPhone.

By default they're going to present to full-screen presentations.

But there's some power under the hood here.

So new presentation styles that are available that we've added, again, that are both available on the phone and the iPad, is an OverFullscreen presentation, an OverCurrentContext presentation, and, I think I mentioned before, popovers are now presentations, as well.

Every presentation has an associated presentation controller, and you can access these with these methods.

And the reason you do so is because you often want to set the delegate on the presentation controller.

And now the plot thickens because the delegate is, in fact, the object that is going to help your presentations adapt to different trait environments.

Before we get into that, let's make sure we all understand what the new presentation styles are all about.

OverFullscreen is kind of a full-screen presentation that doesn't remove the presenting view controller's view.

So you can create interesting kind of overlay types of presentations really easily now.

OverCurrentContext is pretty similar.

If you know what current context presentations are, it's presentations that are kind of constrained inside of the presenting view controller's super view.

So that's what OverCurrentContext gives you.

And, finally, we have popover.

And we all know what popover looks like.

This is a good opportunity for me to say that we're kind of soft-deprecating UIPopoverController.

We're not hard-deprecating it, but you should be aware that all the popover controller, old popover controller API is now being shimmed kind of behind the scenes into a popover presentation.

This might create a couple of differences in behavior.

For the most part, these things are functionally equivalent.

There are a few corner cases, though, that you might run into.

For example, if you have a pop, if you have code that was presenting a popover and then immediately dismissed it and did another presentation the next line, you're going to have to defer that.

And you can do that pretty easily by grabbing a transition coordinator and scheduling the new presentation for after the dismissal of the popover.

So let's talk about how presentations can adapt to changing trait environments.

As I mentioned, all of these presentations, styles, adapt by default in horizontally compact environments to full-screen.

Now, it's possible to change that default behavior to be OverFullscreen or to be not, which means, "Please don't adapt; keep my presentation controller as is, in charge."

The way you control this behavior, as I implied, was you set the delegate and you're going to override a couple, or you're going to implement a couple of methods on that delegate.

So here they are.

The first is adaptivePresentationStyle ForPresentationController.

It does what its name implies.

It's called when the presentation moves into a horizontally compact environment and you return one of those presentation styles that I enumerated earlier.

There's another method that might be a little less clear which allows you to actually return a whole new view controller that should be presented in that style.

And we'll see what that means in a bit.

There's a PopoverPresentation ControllerDelegate, which I'm not going to go into detail about.

But suffice it to say that that delegate, in addition to providing the adaptive APIs, also exposes all of the properties and methods that you need to get the functionally equivalent popover behavior you're used to.

We'll see a little bit of a code example of that shortly.

In fact, very shortly.

So what does it mean to present a popover in iOS 8?

Well, you could use the old APIs, as I said, on UIPopoverController.

But I want to show how you would do it using the new APIs.

So the first thing you do, not too surprisingly, is you set the presentation style to popover.

Now, interestingly you can grab the PopoverPresentationController before you've even presented anything.

That's important because you're going to need to do things like say, "What's the bar button item that I'm pointing to?"

and "What do my arrows look like?"

You might also want to specify a preferred content size so that we know kind of how to size the popover.

And, finally, you present the popover.

So what's that going to look like?

So if I wrote that code and executed it just the way you saw on the previous slide, it's going to look like that.

Now, the first thing I want to say is it is a popover presentation.

The second thing I want to say is there's a couple of problems.

So the first problem is that it underlaps the status bar.

This is one of my favorite bugs.

I can't tell you how many bugs I get about "My content's underneath the status bar."

I'm not going to go into that, but I thought I would just mention that.

The second thing is it looks pretty bad.

And a more subtle point that I'm sure all of you got was, it's a popover presentation and I can't tap anywhere to dismiss it.

Okay, so what are we going to do?

Well, we're going to go to our friend, the trusty presentation controller delegate, and we're going to use some of those new adaptive APIs.

And in particular, I'm going to implement, I would implement adaptivePresentationStyle ForPresentationController.

This time I'm going to have it return OverFullscreen.

I'm going to use this brand new view object that we introduced in iOS 8 called the UIVisualEffectView, which will become your best blurry friend in iOS 8.

And then inside of that implementation, I can adjust the content, like where it's actually positioned.

So that should address a couple of the problems.

So now I get this kind of nifty blurred view, which looks a lot better than that ugly white thing.

I've repositioned my content.

It's a different adaptation.

The reason it's blurring so nicely is because I didn't remove the presenting view controller's view underneath.

However, we still have the problem that there's no way to dismiss the popover.

So how do we fix this?

Well, you might have recalled that there was another delegate API that I talked about that I deferred kind of explaining why I, why it was useful.

We're going to go back to the delegate, and this time we're going to also implement presentationController: viewController ForAdaptivePresentationStyle.

So this is pretty nifty.

What we're going to do is we're going to create a navigation controller whose root view controller is the currently presented view controller.

We're going to add a Dismiss button to that navigation controller's bar, navigation bar.

And then we're going to be good to go.

So now when I hit Note, I get this great looking OverFullscreen adapted popover presentation.

There's a Done button, so I can dismiss it.

So that's great.

But what if I actually just wanted a popover?

Well, you can do that, too.

Let's go back to our trusty delegate friend, and it's this time an adaptivePresentationStyle ForPresentationController.

All I need to do is return None.

And if I return None, the presentation controller is not going to be adapted at all.

And now when I hit the Note button, I get an actual popover.

[ Applause ]

So let's kind of go over what we saw here.

First is, presentation controllers are a new object in iOS 8 that make it easier and more consistent to create powerful custom presentations.

They are an improvement over what was introduced in iOS 7.

Every presentation is associated with a presentation controller, which can be accessed, and you can use that presentation controller to do various things, depending on the presentation control.

But all presentation controllers can use, can have a delegate that conforms to these adapting delegate protocols.

One thing that isn't on this screen is that popovers are also presentation controllers, or are presentations that have an associated presentation control.

And, finally, if you create your own presentation controller-I mentioned this earlier-if it returns YES to shouldPresentInFullscreen, it will be able to adapt.

If, on the other hand, your presentation controller is kind of a current context style presentation, it doesn't really make too much sense for that to adapt, so it doesn't.

We're not going to go through those adaptive delegate calls in that case.

Alright, that's enough for presentation controllers, although this topic actually kind of overlaps or has some overlap with presentation controllers: transition coordinators.

Again, those were introduced in iOS 7.

What is it?

Well, it's an object that conforms to this protocol.

Every transition coordinator has an associated transition, and that associated transition is oftentimes deferred.

And this transition coordinator is kind of holding this freeze-dried transition as it gets passed around to various pieces of code that can then use this method called animateAlongside TransitionCompletion.

So you can kind of queue up blocks of animations that are going to execute in that kind of deferred transition animation that is associated with that transition coordinator.

So that's pretty powerful.

It was introduced in iOS 7, and we're taking advantage of this object in a few new APIs.

So, two of these are viewWillTransitionToSize: withTransitionCoordinator; next one is willTransitionToTraitCollection: withTransitionCoordinator.

Now, I'm not going to talk too much about willTransitionToTraitCollection.

But I did mention earlier that trait collections are kind of associated with coarse application structure.

And one of the best ways to adapt an application-it's not the only way, but it's one-is to implement willTransitionToTraitCollection, and when a trait collection, such as a size class, say, that may change, say, if you rotate a device or if you set an override trait collection, this method will be invoked and you can actually do some coarse-grained application kind of re-jiggering, if you want.

Now, again, there's going to be a whole talk that goes into a lot more detail on that particular method.

It's very parallel to the other method, viewWillTransitionToSize: withTransitionCoordinator that I'm going to talk about.

By the way, did I forget to mention this is part of a new protocol called the content, UIContentContainer?

I mentioned that UIPresentationController conforms to this.

UIViewController also conforms to this protocol.

These objects support a notion of a preferred content size that you can set.

And that's kind of the request, if you will, that you like your content size to grow or shrink depending on the circumstances of your application.

When you set that, your parent container object, whatever that might be-it might be a parent view controller, it might be a presentation controller-will get a preferredContentSizeDid ChangeForChildContentContainer.

In that method, the parent can decide what to do with the request.

If it decides that it actually wants to honor the request, it may turn around and call viewWillTransitionToSize: withTransitionCoordinator on the child, which gives the child the ability to animate alongside that size change.

So let me kind of make a small digression and kind of give a bit of wisdom.

And I realize that Anonymous is actually Josh Shaffer because I think I heard this from him.

And you might wonder, why am I throwing this random point out?

First, let's see what we mean here.

Basically if I rotate a device in general, that's all that's happening.

The fact that there's an animated transform rotation is kind of beside the point.

And most of the time your application really doesn't need to do anything.

It's going to gracefully stretch and do whatever it needs to do as the bounds change.

Okay, so what does that mean?

Well, you will recall that we have these APIs that have been around for a long time.

Well, we're getting rid of them.

And [Applause]-ah, I thought you guys all loved these.

So one of the things about these APIs, and I think I've been on this stage before saying, "You shouldn't do layout based on interface orientation.

You shouldn't use these methods to drive your layout."

They're really kind of focused methods.

You wanted to use them because you wanted to participate in this rotation event.

So now we've generalized it.

We have this other method called viewWillTransitionToSize:w ithTransitionCoordinator that takes over.

So, first of all, all those rotation callbacks can be replaced with this more general notion of viewWillTransitionToSize: withTransitionCoordinator.

I talked about setting the preferred content size and that you get this notification.

Well, so if your widget in the notification center actually wants to request to be displayed in a slightly larger space or smaller space, this API will be called on your widget so that you can, in fact, animate alongside or run some code that executes after the resizing has taken place.

I said that you can, your own apps can respond to this.

Now, at one point I was going to have a whole bunch of slides that showed you how to implement your own transition coordinator.

I didn't have time to do that, but it's relatively straightforward and you can implement your own transition coordinator that's implement, that's kind of associated with your own transition animation.

And if a child changes its size, you can call viewWillTransitionToSize and pass in that object using the transition coordinator.

Okay. So to really be a replacement for kind of the rotation, we kind of had to give a little bit, kind of get down off of our high horses of, you know, the way things should be and acknowledge the way things are.

And we added this target transform.

So it's not so much the orientation that you really care about.

It's like what's the transform that's kind of being, that I'm participating in an animation with?

The reason this is important, and I'm going to get to this later, is we've actually changed where the rotation transforms live.

Some of you guys may have noticed that whenever you do a rotation that it's the root view controller or the full-screen view controller's layer that has kind of the affine rotation transformation directly associated with it.

That's no longer the case on iOS 8.

So when you implement viewWillTransitionToSize, you can ask for the target transform, and if it's not identity, you are inside of a rotation resize event that you can do some interesting things with.

So to show how these are similar or how this is a direct replacement for the old rotation callbacks, this is some, you know, skeleton code where viewWillTransitionToSize first calls myWillRotateTo InterfaceOrientation, which is exactly when it, the old call would have been made.

And then it uses the transition coordinator to animate alongside myWillAnimateTo InterfaceOrientation call.

And, finally, in the completion block is when you would call myDidAnimateFrom InterfaceOrientation.

So you can kind of see that WillTransitionToSize: withTransitionCoordinator is identical or provides the identical functionality.

It's actually more powerful and, from my perspective, it's a lot easier to read code like this.

Okay, I know you guys are all sad that these methods have gone.

So if you don't implement viewWillTransitionToSize: withTransitionCoordinator will still call them, just don't implement it.

A subtle point that you should be aware of is most view controller transitions are immediate when the system calls this method.

What does that mean?

It means that if you needed to rearrange your application's structure in some significant way and you do like pushViewController or something like that, the entire view hierarchy is going to be updated immediately.

So you can do neat things with that in your transition animations.

Unlike rotation callbacks, by default we're going to forward viewWillTransitionToSize through the entire presentation hierarchy, through the entire view controller containment hierarchy.

All you need to do is call super to get that behavior.

If you don't, we will no longer propagate those.

So you probably want to call super.

Finally I'm going to say that you only really need this, I kind of implied it before, when you're doing some kind of special size transition.

More often than not, autolayout and other techniques are going to be-layout techniques are going to more than suffice to handle a size transition.

So I wanted to, I showed this example earlier in the demo and I wanted to show when would be a good time that you might want to use viewWillTransitionToSize.

So here's a collection view controller.

If I rotate it, what's going to end up happening if I did nothing at all, is I get-the default collection view flow layout will give me something like this.

You'll notice kind of how the thumbnails have shifted around and things have resized and maybe that's what I want.

But maybe I want something else.

Maybe I don't want the collection view controller's view to rotate at all, and I want to apply the counter transform on each of the cells.

Something like that.

So this would be a great time to use viewWillTransitionToSize.

And let's see how that would look.

The first thing that you do is you get that targetTransform that I was talking about.

And we're going to invert it, and we're going to grab our old view bounds and set things up for our transition coordinator.

So inside the alongside block, we're going to basically call transition coordinator animateAlongside.

We're going to update the transform to basically undo the rotation transform that's taking effect.

You'll notice that I'm composing it with the existing transform because, hell, I might be in a different orientation already.

So I do that.

I then squirrel away the counter rotation, which effectively is the transform that is, I am animating with right now.

I update my bounds to the old bounds because I've now applied the counter transform on the collection view controller view's transform.

I'm done. I'm going to not rotate, the collection view controller isn't going to rotate, and those cells aren't going to rotate either until I hit the completion block, at which point I'm going to apply the counter rotation to each of them.

Okay, so what did we learn?

Transition coordinators are being used in a lot of our adaptive APIs.

You can use a transition coordinator in response to preferredContent SizeDidChange calls.

All of the rotation callbacks are being deprecated.

That's about it.

So let's talk about screen coordinates.

And this gets to where the transforms are being applied when we rotate.

So in iOS 8-I mean, iOS 7, the screen orientation was always fixed to kind of the top left position in portrait.

This gave you a fixed, unchanging coordinate system, if you needed it.

We ended up communicating things like keyboard size and other things in terms of this fixed coordinate system, even though the actual interface orientation was the current top left corner.

So in iOS 8, we're changing that a bit, and everything is now interface oriented.

So the keyboard size notifications are going to be interface oriented.

A few other things are going to be interface oriented.

But you still may need a fixed coordinate system.

How do you do that?

Well, we introduced a new protocol called UICoordinateSpace.

And, by the way, this is not in seed one.

This will come out in a, you know, a soon-to-follow seed.

We introduced a protocol called UICoordinateSpace, a couple of conversion routines, to and from these coordinate spaces.

It also implements the bounds call.

UIView conforms to this directly, which isn't too surprising.

All the existing conversion routines, by the way, stay in place.

UIScreen now has grown a couple of properties that vend two different coordinate spaces.

One is the default interface oriented coordinate space and the other is the old portrait fixed coordinate space.

So if I wanted to convert to and from that fixed coordinate space, what you effectively do is you grab that fixed coordinate space off of the window's screen and you can convert to and from views.

So let's go over briefly what we discussed today.

We talked a little bit about trait collections, how they affect kind of the gross coarse-level application structure of your application, how you can override them, how view controllers can override them, and a little bit about how your view controllers and your application can adapt to those changes.

We introduced some of the new UISplitViewController features, and there are a lot of them.

I encourage you to kind of look at the header files and attend the talk after this to see all the new and amazing things you can do with split view controller.

There are some new simple properties on navigation controller that will allow you to condense and hide bars.

We've introduced PresentationController and, in particular, we've revamped the presentation hierarchy.

Popovers are now presentations.

We've introduced some new presentation styles.

We've added some new API for transition that utilize transition coordinators, and these are becoming interesting objects that are becoming more present in more and more of our APIs.

We've deprecated the old rotation callbacks or the existing rotation callbacks, can be replaced by-that logic can be replaced by this new method, viewWillTransitionToSize.

And, finally, screen bounds is now interface oriented.

There's a lot of things in UIKit that are new for iOS 8.

This is just some of them.

I encourage you: the talk right after this one is Building Adaptive Apps with UIKit that's going to go into much more detail about all these new and great adaptive APIs we have in UIKit.

Tomorrow there's going to be a talk that goes into depth about presentation controllers, how we internally use them to implement new replacements for search controller and alert controller.

We are, there was a talk yesterday, I believe, about creating extensions that leverage the viewWillTransition ToSize APIs.

There are some nice talks on Friday, or there is a nice talk on Friday about how you can make your, basically your transition animations, more responsive to user interaction.

For more information, please contact our evangelist, Jake Behrens.

He'll be more than happy to get you the sample app and answer your questions and tell you how it all works.

And have a great rest of the conference.

Thank you.

[ Applause ]

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