Video hosted by Apple at devstreaming-cdn.apple.com

Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: tech-talks-2013-13
$eventId
ID of event: tech-talks
$eventContentId
ID of session without event part: 2013-13
$eventShortId
Shortened ID of event: tech-talks
$year
Year of session: 2013
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2013] [Tech Talk 13] Architecti...

iOS 7 Tech Talks #13

Architecting Modern Apps, Part 1

2013 • 47:38

See how technologies like Text Kit, Dynamics, and Auto Layout make it easy to build flexible, modern interfaces. Gain expanded control over your user interface with powerful new animation APIs to enable custom transitions.

Speaker: Dave DeLong

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Welcome to Architecting Modern iOS Apps, Part 1. My name is Dave DeLong, and I am one of the App Frameworks evangelists. In this session, we're going to be taking a look at some of the great new features of the iOS 7 SDK and peeling back the hood and looking at how some of these features actually work.

We're going to be focusing on three main areas. The topic of motion, which we've already heard a little bit about. The changes to UI view controller. And then we're going to finish up looking at Text Kit. So first up, motion. The first part of motion, as we've already heard a little bit about already from Mike, has to do with motion effects.

Motion effects are a great way to add subtle depth to your user interface. Let's take a look at an example. On this screen, you can see an alert view being shown in the Safari app. And we can tell simply by watching this that there is depth, that the alert view is floating on top of the tabs.

And it's kind of hard to see how this is actually happening. But for emphasis, I want to show what this UI would look like if we didn't have any motion effects applied. So... Here's that same screen again, except on the right, we have removed the motion effects. You can tell that on the right, the interface feels much flatter. There is no depth to it. Whereas the normal interface on the left feels much more natural.

But as you're watching this, it's hard to intuit what is actually going on. So here it is again. Except this time, I've removed the perspective as the screen moves around. So what we can actually see is happening is that we're simply repositioning the alert view as the user tilts their device. That's all we need to do to add that motion effect to this alert view to get this wonderful feeling of depth to our interface.

is a very good example of this. It is very trivial to do this in iOS 7 using the new UI Motion Effect class. This is an abstract class. It is extremely easy for you to subclass. There is simply one method, I believe, you have to override. And through this method, you receive processed updates from the accelerometer.

These updates give you a value that you can use to represent some sort of change. Now, this is all very abstract. And so to make it easier for you, we have created a concrete subclass of this called UI Interpolating Motion Effect. And it is probably this class that you are going to be using the most in your applications. Here is how it works.

First up, we're going to create an interpolating motion effect to say that we want to alter the center.x property of our view. So we want to alter its horizontal position. And we want to change the view's horizontal position as they tilt their device along the horizontal axis. Next, we need to specify a relative range of values. And so here we're going to say that we're allowed to shift our view up to 40 points in either direction.

I want to point out here that these values are not primitives. They're not a float or an integer that you're passing in. It's an actual object. And that's because interpolating motion effect can operate on much more than scalar values. You can interpolate between arbitrary affine transforms, for example.

Next, we're going to create another emotion effect, but this time alter the view's center.y property, so it will shift along its vertical axis. And again, like before, we specify a range of values, so again allowing it to shift up to 40 points in either direction. Now, at this point, we could take these two motion effects and apply them to our single view. But for the sake of efficiency, we're going to group them. We're going to do that with another UI Motion Effects subclass called UI Motion Effect Group.

Now, the advantage of grouping motion effects means that we can take the updates provided by these two motion effects and apply all of their changes to our view in a single operation. If we did not group them, then first, as the motion effects receive values from the accelerometer, the first motion effect would alter the view's center.x property. And then the second motion effect would alter the view's center.y property.

But by grouping them into a single motion effect group, we can alter both the x and the y values simultaneously. So with the group created, we simply use the new method on UIView, addMotionEffect. And that's all we need to do to add a motion effect to our views.

So that was motion effects. Very easy. The next thing I want to talk about in the topic of motion is dynamics. If you haven't heard about this already, Dynamics is a very easy way to add realistic physics-like interactions to your views. We have a physics-like engine under the hood that performs at frame rate calculations to move your views around and see if they're colliding with each other. We can have your views attached to springs. We can affect them by gravity or even attach them to arbitrary points. The possibilities here are endless.

One thing I want to do point out about Dynamics, however, is that this is not meant to be a game engine. Dynamics exists to enhance your interface, as it already is. It's not meant to create some new game. For that, you would want to look at SpriteKit. As Mike has shown us already, we're using Dynamics on the lock screen to give a lifelike feel to this lock screen view. So we can see that there's elasticity to the view that affects how high it bounces. It reacts according to how hard you throw it down. If you drag the view up and then slam your finger down, the view reacts accordingly. It is very lifelike in its interaction.

So we're not going to get too in-depth into Dynamics in this session, but we had three sessions at WWDC this year that went in-depth into all of the things that you can do with Dynamics. We're going to take a little bit of a look at them in a few minutes as we look at custom transitions, but I highly encourage you to check out these three sessions. Next, let's talk about custom transitions. The motion effects that we saw, you can use to add subtle movement to your interface. And with Dynamics, you can add realistic movement.

With custom transitions, as we saw in Mike's presentation earlier, you can model movement between entire different areas of your application, like we saw in the photos example. These are transitions that can be contextually relevant and very engaging and provide a lot of information to the user simply in how views move around the screen.

Now, if you've taken a look at the API, it might be a little bit complex, because everything in this API is defined by protocols. It's very abstract. However, having a protocol-based API allows us to have an extremely flexible API. And we're going to see how these protocols play with each other to give you the power of implementing custom transitions. Now, two key things to know about custom transitions is, first, that the animations happen in a sandbox.

UI Kit really likes it when your app stays in a consistent state. And when you're in the middle of a transition, you're not always in a consistent state. Some view controller might be partially on the screen, another might be partially off the screen, and so on. And so to keep UIKit happy, we'd perform these transitions in a sandbox. And then it's up to you to tell the framework when your transition has completed.

But with custom transitions, you can implement, for example, your own crossfade transition, where you can easily crossfade between, for example, this beautiful orange view and a green view. This is about the extent of my design skills. So what are the objects involved? Well, the very first thing is called the transitioning delegate. This is a new property on UIViewController.

When a view controller is presented in iOS 7, it will first ask its transitioning delegate, "Do I have a custom transition?" will provide an object. By providing an object, the delegate is saying, yes, there is a custom transition involved. If it returns nil, then there is no custom transition, and it should go with whatever the default is. Now, the transitioning delegate will differentiate between the presentation of a view controller and the dismissal of a view controller, and we'll see in a few minutes why that can be extremely useful.

So the object that the transitioning delegate returns conforms to the animated transitioning protocol. This animated transitioning protocol defines two key pieces of information. The first is how long the transition takes. And the second is what the actual transition is. The other thing that this transitioning object needs to do in its implementation of these methods is report when the transition has actually completed.

It reports that via an object that's passed in as a parameter to one of these methods, that is the transition context. An object that performs to the protocol UI view controller context transitioning. You'll almost never need to create one of these objects yourselves. They are provided by the framework for you.

And as its name implies, this object contains metadata about the transition. It includes information as to which view controllers are participating in the transition, what the sandbox is, what their initial and final frames might be, and so on. And it is through this context that you report that the transition has completed. So let's see how these objects all play together. Let's start by presenting a view controller. As we learned just a minute ago, the ViewController is going to ask its transitioning delegate if it has a custom transition.

In our case, we do have a custom transition, so the transitioning delegate will create one of these animated transitioning objects and return it to indicate that, yes, we do have a custom transition. This object is passed back through the view controller to the framework, which keeps a reference to it. Next, the framework will tell the animated transitioning object to animate, to perform the transition. And along with this message, it provides the context for the transition that indicates the view controllers involved, and so on.

Now, when the animated transitioning object receives this perform transition method, It can now do whatever animation it wants to to actually perform the transition. When that animation has completed, the animated transitioning object then tells the context that it is finished. And the context passes that information back to the framework. The extra objects are cleaned up, and that's a custom transition.

But this is a very simple custom transition. This is one that would have a predefined animation. But there are times when we want to have a transition that's actually defined by the user interacting, perhaps, with some objects on the screen. So for that, we need to do an interactive transition.

An important thing to realize about an interactive transition is that the interactive portion of the transition actually happens before the animation. If you're familiar with the drag from the left edge of the screen to go back gesture that's new in iOS 7, You don't actually have to drag your finger all the way across the screen to go back. You can just drag it part of the way. And when you release your finger, there's still some animation that needs to be performed to return the views to a wholly consistent state.

Dave DeLoong And so the first part of that gesture, or the first part of that transition, as you're dragging your thumb or finger across the string, is the interactive portion. And then when interactive ends, the interactive portion ends, there is still animation to be performed. Dave DeLoong And so that is why the interactive portion comes before the animation. Like we saw before, these methods are defined on the transitioning delegate.

So going back to the lock screen example, this is an interactive transition. We are transitioning between the slide to unlock screen and the camera view that's behind. It's interactive because it's defined by a gesture. We have no idea how long it will take. The user could place their finger on the screen and just move it up and down for hours. We really have no idea what they're going to do.

and the framework needs to accommodate this. So we do. We do this with an interactive transitioning object. This is another object that's returned by the transitioning delegate. And it is an object that watches for interaction and notifies, via the context, how the interaction is happening. It will notify when it is canceled, or it will notify when it is successfully completed.

Now, to make this a little bit easier for you-- it's not all protocols-- we have implemented the interactive transitioning object protocol for you on a UI percent-driven interactive transition. This is a concrete implementation of the interactive transitioning protocol. And it will work out of the box with any UIView animation API.

You can simply wrap up your UIView animations inside an animated transitioning object, then supply one of these percent-driven interactive transitions, and just like that, your UIView animation calls will become interactive. It is easily subclassable, so you can tweak things. Very easy to use. So let's see how this fits in. Again, with the ViewController that we want to present.

Like before, the View Controller has its transition delegate, except now, Well, it will first again ask if there's a custom transition. And like before, we have a custom transition. And so we're going to create that same animated transitioning object and return it back to the frameworks. Except now-- The View Controller is also going to ask its transitioning delegate, "Do you have an interactive transition for me?" Or in other words, "Is this animated transitioning object that you just gave me part of an interactive transition?" And the transitioning delegate will return an object that conforms to the interactive transitioning protocol. Might be the same object, might be a different one. That's why they're protocols. And by returning this interactive transitioning object, we indicate that this will be an interactive transition. And that object, as well, is given to the framework.

Except now, since the framework has both the interactive transitioning object and the animated transitioning object, it first starts with the interactive portion of the transition. And it does that by telling the interactive transitioning object to start watching for interaction. And with that message, provides that same context that we saw earlier. Now, this interactive transitioning object can be watching for any sort of interaction. Most commonly, it's going to be a gesture on the screen. And as the user moves their fingers across the screen, you're going to be performing something.

You're going to be doing some calculation to figure out approximately how much of this transition has completed. And you're going to be notifying, via this context, how much has occurred. Maybe 20%, then 42%, then 60%, and so on. And you're going to send this update message as many times as you want.

At some point, however, the user will lift their finger off the screen. That is inevitable. And when they do, it's up to you to decide if they have moved the views involved far enough for the transition to complete, or if things should be reverted back to their initial state.

We do this. We make this decision and indicate to the context whether we should finish the interactive portion or cancel the interactive portion. The context stores this information and relays on to the framework that we are done with the interactive portion of our transition. But remember, we're not done yet, because we still might need to perform some cleanup animations. And so, this is where the animated transitioning object comes in. And like before, it is told to animate, and is again given that same context.

It again will perform whatever animations it wants. perhaps it doesn't need to perform any, and it will notify it through the context that it is finished. When the context gets this final message that the animated transitioning object has finished its animations, then all of these extra objects are cleaned up.

and the animation and transition complete. So this is a lot of information. So what I want to do now is I want to switch to the demo machine. and show you how we actually build an interactive custom transition. So again, I have employed my wonderful design skills. I have a lovely orange view here with a single button that says Present. And when we tap this button, it is going to present my green view.

So let's see how we're going to do this. In my first view controller, I'm going When we tap the button, we're going to create our second view controller and set the second view controller's transitioning delegate to be the first view controller so that as the second view controller is being presented, it will ask the first one if it should be done using a custom transition.

And here, it will ask us through this wonderful method, animation controller for presenting controller source controller. We love long names. And here, we're simply going to create a crossfade transition and return that. It's all we're going to do. This crossfade transition is very trivial. We're going to define that this is a transition that will take approximately two seconds.

This is so that it's easy for you to see the effect that it's going to perform. And then in the actual animation, will retrieve some information from the context, such as the view controllers involved, the frames that they're coming from, and going to the sandbox view in which these animations take place.

And then all we're going to do is simply change the alphas of these views to fade out one as we simultaneously fade in another. And this is how we're going to do our crossfade. Now, when this animation completes, like we learned just a few minutes ago, we need to notify to the context that we finished. So that's how we do this here, using this complete transition method. And by passing in yes, we are indicating that this is a successful transition. So let's run this.

And I can tap here on this Present button, and I get a nice, wonderful two-second crossfade. So what about this drag down to dismiss? Well, on the second view controller, things get a little bit more complicated. So here, as the view loads, I'm going to create a drag to dismiss transition object and give it a source view. Now, by doing this, the drag to dismiss transition is going to create the gesture recognizer to detect the drag.

And by assigning this dismiss transition a delegate, it can notify to us when the user starts dragging on the screen. So when we first notice the user dragging on the screen, we'll set our transitioning delegate to be ourselves. Now, this is kind of curious, because if we didn't do this, then as we started dragging to dismiss their second view controller, it would still be trying to ask the first one how it should dismiss. But the first view controller doesn't know anything about the gesture recognizer involved in this transition.

And so we're going to set this view controller to be its own transitioning delegate, such that when we are asked for the animated transitioning and interactive transitioning objects, we have an actual object that we can return. And this is where the power of this API comes into play, because we are going to return the same object as both the animated transitioning object and the interactive transitioning object.

So this is a single object that has a dual purpose. This is why protocols are so wonderful. So let's take a look at this drag to dismiss transition. So like I said, when we create one, we're going to create a pan gesture recognizer and add it to the view so that we know when the user starts dragging.

And when the user starts dragging and gesture recognizer state began, all we're going to do is notify to the delegate that the drag to dismiss transition did begin dragging. As we saw a second ago, this will dismiss the view controller. And since we are returning this object as the interactive transitioning object, We will get this message from the framework: Start interactive transition.

So like the crossfade animation, we still need to set up the sandbox. So this is very similar code to what we saw just a few minutes ago, where we're going to retrieve the view controllers involved, get their frames, add them to that transition container. And we're going to remember some information about where the user was touching on the screen so that it can be moving relative to the finger. But that's all we're going to do.

Now, as the user continues to drag and the gesture recognizer state changes, we're going to simply update the center property of this view so that it will move with our finger. And as we do so, we're going to tell the context to update and give it an approximate percentage completed, so a number between 0 and 1, indicating how much of this transition we have approximately done.

And all we're doing here is we're simply estimating this based on how far down the screen the view has moved. Now, at some point, though, the user is going to lift their finger off the screen. And when they do, we need to figure out if we should finish the interaction or if we should cancel it.

So here I have decided that if they move the view at least a third of the way down the screen, then we should consider that good enough and we'll finish the transition for them. And if they're still in the top third of the screen, then we will cancel it and go back to the beginning. Let's look at the success case.

Here, we're going to get a little fancy. We're going to use Dynamics. So Dynamics, with Dynamics here, we're going to set up our dynamic animator, which is kind of like the physics engine. And we're going to give it the reference view of the container so all of the physical interactions will happen within this container.

And all we're going to do is we're going to create some gravity. And we want the view to fall off the bottom of the screen. And so we're going to give it a large gravity so that we're not waiting it to slowly accelerate down. So we're going to give it a vector down of 4.

And then we're going to use this property of a dynamic behavior called the action block. And the action block is an arbitrary block of a UI dynamic behavior that gets executed on every tick of the physics engine. And we're going to use this block to determine if the view has totally fallen off the screen. So the action block is a great place to perform this check, because it's going to be updated every single frame, every time the view moves. And since it's falling, it's always moving.

And so we're simply going to look is the percentage completed greater than one, which would mean that it's all the way off the screen. And if it is, then we will turn off our dynamic animator by removing all of the behaviors and tell ourselves to complete the transition.

So that's what the action block is going to do. But then to finish this up, we just add the gravity behavior to our dynamic animator and then tell our context that we are now done with the interactive portion. is the first person to use the Gain app. He's the first person to use the Gain app. And he's the first person to use the Gain app. So he's the first person to use the Gain app. And he's the first person to use the Gain app.

And here we're going to do something, again, kind of similar, again, with Dynamics. So that same sort of setup, except here we're just going to snap the view back into place using a snap behavior. So we give it a view to snap into place and give it a point to snap to.

And we're going to give it a load damping, which means that it's going to oscillate a lot so we can see that it's actually snapping. And again, we're going to use the action block to know when this is approximately completed. And we're going to do that by looking to see if our frame is within one point of its original location.

[ Transcript missing ]

We will make sure the view is actually in its original location. Again, remove all the behaviors to turn off the physics engine and then complete the transition. So we add that snap behavior to our animator, and then say, because the user didn't drag far enough, that we are going to cancel the interactive transition. So the user lifts their finger off the screen. We're either going to drop the view off the bottom of the screen or it will snap back to its original place.

When either the view has totally fallen off the screen or has finished snapping back into place, we're going to complete this transition. And here, all we really need to do is tell the context that we are done. And when the context receives this message, complete transition, then the entire transition is totally complete and everything will go back to being in a wholly consistent state.

So let's run this again. Like we saw before, we can tap to present and get this nice little two-second crossfade. Now I can tap on the screen, drag down, and if I only drag down part of the way, when I release my finger, it's going to snap back into place, like this.

And we could see that by having a low damping, we saw that oscillation going on. But if I drag down further, so more than a third of the way down the screen, when I release my finger, it's going to fall off the bottom like that. So these are some of the neat things that you can do with custom transitions. The possibilities are endless. That was a brief look at custom interactive transitions.

Now this is great for defining your own transitions. But what about built-in transitions? What if you want to participate along with those? Many of you have been requesting throughout the years that you want to know-- you want to participate with the built-in transitions. Maybe you want things to animate alongside everything else. Well, I'm happy to announce that in iOS 7, you can totally do that.

There is yet another protocol involving coordinating transitions. You can receive this transition coordinator while a transition is in flight. And via this transition coordinator, you can attach extra things to animate along. You can receive updates about when the transition completes. You can get that same context, and so on. You can now participate in built-in transitions. And that is a look at Motion in iOS 7.

So let's move on to UIViewController, the heart and soul of every iOS app. You should all be familiar with UIViewController. So we made some changes to ViewControllers in iOS 7. The first one has to do with a concept that we call extended layout. In iOS 6, the content of a view controller lived below the navigation bar in this area. In iOS 7, we are putting the emphasis on the user's content, which means we want their content to fill the screen. And so now the content extends-- hence extended layout-- to fill the screen and takes up the entire screen. And so the content underlaps the status bar.

This behavior is controlled by a new property on UIViewController called the edges for extended layout. And by default, it is rect edge all to indicate that all edges of your view should extend to fill the screen. However, if you like, you may change this. Maybe you have content that doesn't need to go behind the status bar or is not large enough.

You can change this property, for example, to UIREctEdgeNone to indicate that your content should still live below the navigation bar and above a tab bar, for example. This behavior of having content move behind the status bar, though, means that we need to change a little bit how scroll views work.

Because we still want scroll views to scroll behind the status bar, but we don't want them to start behind the status bar. That would be very awkward. We would be chopping off the top approximately 64 points of our content. And so we have another property. on UI View Controller to automatically adjust the content insets of your scroll bars to account for navigation bars and tab bars.

We call this property automatically adjusts scroll view insets. And the default for this property is yes, which means that the scroll view itself will still extend to fill the screen, as the edges for extended layout property defines. However, the content will come to rest below the navigation bar, or above the tab bar.

We adjust both the content inset and the scroll view indicator inset, so it still looks like your scroll view is still positioned between the navigation and tab bars, but will scroll behind them. I should mention, however, that if you are performing any sort of manipulations to the content insets of your scroll views yourself, you should really turn this off, because we can't anticipate how your content insets will change. And so if you leave this on while changing the content inset, you can really confuse your scroll views. So turn this off if you're changing those yourselves.

Now, because content scrolls behind the status bar, we also need to change how we refer to the status bar. So on iOS 6, we had a solid color background, a tinted background. You could even define your own custom color for it. But now in iOS 7, the status bar actually doesn't have a background. It is transparent and simply takes on the appearance of whatever is behind it. This means that we need a new way to refer to how a status bar looks. So we're going to take the status bar style that we're used to and change its meaning slightly.

So we're still going to have UI status bar style default. And what this means is that the default style of the status bar's content, so the signal strength indicator dots, the time string, the battery percentage, all of that should be darkly colored because the status bar itself is on top of light views.

In this case, a white one. Then there is the other style, which is UI status bar style light content, which means that the contents of the status bar themselves should be lightly colored because the view behind it is a dark colored view. Now the other big change that we've made to view controllers is that you can now specify the style of the status bar on a per-view controller basis. Prior to iOS 7, you had to manually manage the state of and style of the status bar through these methods on UI application.

Fortunately, you don't need to worry about that anymore because we have new methods on UI view controller to do this. So there's a method you can override on your view controller called preferred status bar style to indicate how the status bar should look when this view controller's view is behind it. So the default is, of course, status bar style default, but you can override this to return the light content style instead.

or maybe you want the status bar to be hidden entirely. So you should override. The prefersStatusBarHidden method to return yes, so that you want the status bar hidden. Or you can leave it as no to say that the status bar should be present. Now, there are situations where we want the status bar to come and go dynamically.

And so if you want to change the visibility or style of the status bar, you can do that now by this new method on UIViewController called setNeedStatusBarAppearanceUpdate. When you invoke this method, we will re-ask the view controller what the preferred style for the status bar should be, and we will apply those styles to the status bar. And when you invoke it like this directly, the changes are applied instantaneously like this.

As we learned about in the previous session, this can be a bit of a jarring transition for the user. We want more animation to indicate that the status bar has actually disappeared. Maybe it's faded or slid out or something. And so it's really easy to control that now simply by wrapping that call to setNeedStatusBarAppearanceUpdate inside a UIView animation block.

I hope you're realizing the implications of this. In iOS 7, you can now have explicit control over the animation of the status bar. You can control the timing duration, the animation curve. You can make it appear and disappear as part of a keyframe animation. The possibilities are endless. So by putting this call inside this animation block, the status bar will now nicely fade out.

Like that. But as I said, maybe you don't want it to fade out. Maybe you want it to slide. So you can override yet another method called Preferred Status Bar Update Animation and return the slide animation style to indicate that the status bar should instead slide off the top of the screen like this.

So those are some of the changes to the status bar. You can now customize it on a per-view controller basis. Because content now moves behind the status bar, we have this concept of extended layout and automatically adjusting scroll view insets. With the changes to the status bar as well, you can have explicit control over the animation of the status bar. A lot of things that were very, very difficult to do in previous versions of iOS. Those are some of the changes of UI View Controller.

I want to finish by talking about Text Kit. Text Kit is not a framework whose headers you've been unable to find. There is no textkit.h hiding anywhere inside the SDK. It is part of UI Kit. However, we felt that the changes involved to text layout and text rendering were so significant that it warranted its own name and its own icon. And so we created this name of Text Kit. But it really is just part of UI Kit.

But with Text Kit, your apps can do beautiful page layout like this, where you have your content divided into pages. And within each page divided into columns, you can have your text wrap around objects, such as this text that is wrapping around a trophy. You can have rich text attachments, like this ornate T at the beginning of a paragraph. All sorts of beautiful things that you can do.

Now, chances are most of you are not writing an app like Pages. And so most of you probably won't need to build something like this. However, that does not mean that Text Kit is not for you. We're going to talk about three key features of Text Kit that you all should be starting to use in your apps today.

But if you really want to know more about the pagination and page layout and so on that you can do with Text Kit, we again had three sessions from this year's WWDC that I would highly encourage you to go watch. But the three features that we're going to focus on in our few remaining minutes are text styles, dynamic type, and font descriptors. So text styles are pretty simple. It's simply a way to refer to a font by its purpose.

And so we've defined these constants in UI Kit to refer to a font that might be used for headline content, or a font that might be used to stylize your body, your primary content, or a font that might be used to stylize text that appears underneath an image as a caption.

Dave DeLoong So this is text styles. By simply invoking a class method on UI font called preferred font for text style and passing in one of these constants, you will get back a UI font that is customized for that scenario. So this is a very easy way to not have to worry about...

[ Transcript missing ]

or a large font size. We should be respecting the user's preferences. Now, how do we do this? Well, it's very simple. We use these text styles that I just talked about. When you ask for the preferred font for one of these text styles, we will give you back a font object that takes into account the user's chosen content size in the Settings app.

But like other parts of the Settings app, this content size can change while your app is running. And so to react appropriately to that, you would need to listen to this new notification called UI Content Size Category to Change Notification. When you receive this notification, this would be the appropriate time to get new preferred fonts and reapply them to your interface. Going back to this slide.

As you watch the text size of these cells change, what I want you to notice is what does not change. And that is the text in the navigation bar. Because this slider in the Settings app is affecting the content size of the content. And the text in the navigation bar is not part of the user's content. That's simply part of the navigation of the app. Again, this goes back to the principle of putting the emphasis on the user's content. So that's dynamic type. The third feature of Text Kit that you all can start using today is called font descriptors.

If we think about where fonts fall in the model view controller pattern, they really are actually kind of objects at the view level because they describe how things look. They're really only ever used with views. They're kind of view level objects. So we can think then of font descriptors as the model that backs a font.

A font descriptor will contain all of the information about the font, what font family it is, its face, its point size, its attributes, and so on. It is very, very cheap to create these objects. You can create loads of them and not be adversely affected by that, whereas that would have been very difficult to do with UI font. One of the other neat advantages of font descriptors is that it makes it easy to compose fonts.

So you can say, give me the font descriptor for this one font, but apply in this point size of another font and the attributes or the traits of a third font. And using font descriptors, you can build up combinations of fonts in ways that would have been somewhat difficult to do before.

These fonts, as I said, are extremely cheap. They're easy to archive, so you can include them in whatever objects you're writing out to disk. And these should be the primary ways that you refer to fonts in your code. And then only convert these font descriptors to actual font objects as you are about to place them in your user interface.

But where font descriptors come in is that they make it really easy to emulate dynamic type if you're using custom fonts in your app. So let's see how that would look. Like I mentioned, we need to listen to this content size category to change notification so that we know when the user changes that slider in the Settings app.

And when they do-- We will ask the UI application object for the preferred content size category and get back a constant that indicates whether they want their content to be small, medium, large, extra, extra large if they have accessibility turned on, and so on. And here, in each one of these cases, we would create the font descriptors that are appropriate for a headline font style, a body text style, and so on.

And like I said, we can compose these font descriptors by taking attributes of various fonts, combining them together, and so on. So, using font descriptors, you can still take advantage of the dynamic type feature while still using custom fonts in your application. So, those are just some of the ways that you can adopt Text Kit, even if you don't have an app that's complicated, like Pages, because there is a lot in it that everybody can use. So, you can use... Text styles.

Use UI font descriptors for referring to your fonts in a cheap and easy-to-use way. And, of course, listen to the dynamic type notification so that we can react intelligently to the user's decisions. And that's a brief look at Text Kit, and it completes our tour of new features in UI Kit in iOS 7.