Good morning, and welcome to What's New in Cocoa Touch.
I'm Eliza, and I'll be joined shortly on stage by Josh Shaffer.
And today, we have a ton of great new APIs to tell you about.
We're going to start with some of the brand new productivity APIs for iPad and iPhone.
After that, we'll show you some of the refinements to the User Interfaces on these devices, and we'll talk about how you can get these effects in your own applications.
And finally, we'll go through an assortment of additions and improvements to existing APIs across Cocoa Touch.
So, the most important productivity API in iOS 11, as you heard in the keynote, is Drag and Drop.
This is an incredibly powerful API.
Here's a video showing a couple of the things that it can do.
So, I can pick up an item, drag it around.
I can tap to add additional items to the drag.
The system remains fully interactive while my drags are in progress, and I can even drag data between different applications.
So, we're really excited for you guys to be adopting this API in your apps.
And there are no fewer than four sessions this week, telling you all about how to do that.
So, right now, I'm going to give you just a very brief overview of some of the key components of this API, beginning with enabling drags in your application.
So, suppose you have a custom view with some sub-views, maybe little icon like views, here, that you want to make draggable.
What you'll do, is create a UI drag interaction, which is a new subclass of UI interaction.
And you'll attach it to the view that you want to allow the user to drag.
Now, a UI interaction is kind of like a gesture recognizer.
You make one, you set a delegate on it, you attach it to a view, and then, the system takes care of the rest.
Your delegate will be called back to provide information.
It's really quite easy to use.
So, here we would create a drag interaction object, assign ourself as a delegate, attach it to this view.
And we would also, do the same for the other views that we want to make draggable.
Now, the UIDragInteractionDelegate protocol gives you a ton of opportunity to customize what's going on with this drag.
The one thing you absolutely have to do, is provide the data for the item that's being dragged.
But apart from that, it's entirely up to you.
You can go with the system defaults, or you can customize all kinds of aspects of the drag.
Like, the lift animation, the previews, you can get callbacks as the touch moves around on the screen and do things in response.
It's entirely open to your application's needs.
So, the other major component of Drag and Drop, obviously, is the drop component.
And to enable that, you also use a new type of UI interaction called the UIDropInteraction.
And you attach that not to the individual draggable views, but to the super view, the container that's going to receive items dropped.
Once again, you set a delegate.
And once again, this delegate has the opportunity to do all kinds of customization.
You can update your UI to make the other items get out of the way as the drag moves around, show a visual indication of where a drop would go, what would happen if the user were to drop.
You receive the data when the drop is actually performed and you can update your model in response.
And then, you can also customize all kinds of aspects of this animation.
You can customize the preview, during the drop, the drop animation itself, it's really very powerful.
So, we're excited to see what you will create with all of the power of this feature.
But to make it really easy to get started, the system has built-in support in a number of the existing classes that you're probably already using.
So, to get this going with TableView, CollectionView, and the various Text and Web views, there's very little work for you to do, in addition.
One other useful piece of integration on this system, is with UIPasteConfiguration.
So, if your application already knows how to handle the paste part of a copy and paste operation, there's very little extra work that you need to do to make that same view a drop target.
So, here are the sessions on Drag and Drop.
And the first one is introduction to Drag and Drop, right here, right after this session.
And so, we really encourage you to stay for that.
Tomorrow, we have Mastering Drag and Drop.
And then, there's an entire session devoted to getting Drag and Drop working with your table and collection views.
And a really important session on the various ways that you can manipulate data with your drags and drops.
There's actually a lot that you can do there, that's very powerful.
So, we encourage you to check that out, as well.
So, the other piece of our productivity enhancements on iPad and iPhone is File Management.
We're introducing this wonderful view controller that allows your users to browse their documents, right in your app.
And this gives them access not only to the local documents in your app's documents folder, but also, to documents stored on the cloud in iCloud Drive, and also in participating third party cloud storage services.
To make one of these.
So, the class is called UIDocumentBrowserViewController.
And to make one, you pass it in array of the file types that your app knows how to handle.
That way, the user can't open a file using this API that your app doesn't know what to do with.
And this class is actually quite customizable.
The appearance can be changed in a variety of ways.
And you can also set different behaviors to occur as the user navigates their files and selects one.
As I mentioned, this gives you access both to local storage, and documents stored on the cloud.
And that comes with one important caveat that's really important to keep in mind.
Which is that you can no longer depend on your application being the only one touching a particular file at a given time.
So, it's really crucial to coordinate file access with documents that you're accessing using this class.
And you can do that by using NSFileCoordinator, directly, or by sub-classing UIDocument, which builds in a lot of file coordination behavior for you.
To hear more about this class and other document based topics, please check out this session on Thursday.
And now, I'm going to invite Josh onstage, to talk us through some of the UI refinements in iOS 11.
[ Applause ]
So, there's a lot of really great enhancements to productivity APIs in iOS 11.
But we've also got some really great UI refinements, as well.
And I want to talk through a bunch of them, starting with one of the most visible, which is the new large title at the top of the navigation bar.
And this is the most visible change that you'll probably immediately notice, when you start using iOS 11.
It includes this new large prominent title displayed at the top.
Along, with a new unified search field design that integrates it right in the bar.
So, while your content is scrolled to the top, you're going to be able to have easy visibility of the large title that tell exactly where you are, and easier access to the search field.
Because it's now pulled down a little bit farther than where it usually would have been, in the past.
However, to maximize the area available for displaying your actual content, as you start scrolling, both of these will collapse in order to maximize the space below the bar, so you can see as much content as possible.
First, the search bar will collapse itself.
And then, the large title will scroll up under the bar, and you'll end up with a view that looks very much like what you were used to, prior to iOS 11.
Now, UINavigationController will automatically find the main primary content scroll view inside of your currently visible view controller.
And track its content offset to make sure that it can do this on your behalf.
So, in most cases, there's actually not a lot of work that you need to do, in order to adopt that.
Enabling all this behavior is actually really straightforward.
There's one new property on UINavigationBar called prefersLargeTitle.
And if you just set that to yes, you're going to get the large title appearance and NavigationController will automatically do that tracking that we just talked about.
Finding your scroll view, tracking its offset, and handling the shrinking.
Now, the second thing is a new property on UINavigationItem.
And this lets you control the appearance of the large title for every level of your navigation hierarchy.
So, not every level, as you're pushing view controllers onto the Navstack, needs to display the large title.
And in fact, many often do not.
So, you can control at each level using this navigation item property, whether the large title, or the older more small traditional style is what you'll see at any given point.
Adopting the searchController appearance is also, really easy.
You can just use this new searchController property, in order to get that new appearance and all the new behaviors.
Now, traditionally in the past, you would have taken your navigation bar and probably included it as part of your content, maybe made it the table header view for your UITableView.
Now, instead of doing that, because the new appearance looks more like it's part of the bar, you can just use this property and you'll get all those behaviors.
Now generally, the first view on your navigation stack is the only one that you would use the large title for.
This is a general bit of guidance for designing your apps to use these large titles.
Then, as you push in to a second level view and keep navigating deeper, you'd usually use the more smaller traditional size.
This is a great starting point for your designs, but as we just mentioned, it is fully under your control via the API, so you can do the right thing for your app.
And in fact, if you look through some of ours, you'll find that Mail, for instance, uses the large title at the first two levels.
You'll also notice that the refresh control is now integrated in this new, single, large title.
Now, if you use a UI refresh control in your app to get your Pull to Refresh behavior, this will actually happen automatically.
So, there's no additional work you have to do to get that visual integration with the bar.
One important thing to note about these large titles and the bar is that they're actually part of the navigation bar, not part of your content view.
As a result, the navigation bar itself, is actually quite a bit taller than you might normally be used to from previous releases of iOS.
And in fact, it can now change height as the content scrolls.
As you can see, it's larger while the large title is visible.
And then, as the user scrolls and the large title disappears, the navigation bar takes on a more traditional height as you would normally be used to.
Now, you might initially be concerned that this could be complicated to deal with.
But the teams have been working really hard to make sure that this is as easy as possible to deal with, in your apps.
And in most cases, it can actually be handled automatically on your behalf, with no additional work.
UINavigationController does a lot of this for you.
Now, to make it easier, though, to find out as these bars change height, there's a new property on UIView, that's actually really generally useful and can apply across your entire application.
And that's the new safeAreaInset property.
So, safeAreaInset lets you know the area of your content that is visible underneath anything that might be obscured by bars.
So, you can reliably and easily place your content in the area that will be visible and not obstructed by any of these other system UIs, like the bar at the top and bottom.
Now, with this information, you can easily do that layout.
And as the bar changes height while the user scrolls, the safeAreaInset will grow so that you can easily stay below the bar.
Now, if your view is overlapped by a toolbar or a tab bar on the bottom, you're going to find that the safeAreaInset has a value for its bottom, as well.
So that you can be sure that you know the exact area, top and bottom, that you can safely display content in.
The safeAreaInsets are really easy to access, too.
So, there's three new properties on UIView that make it easy to use this.
The first is the safeAreaLayoutGuide.
Now, with safeAreaLayoutGuide, you can easily integrate safe areas with all of your auto layout code.
So, you can set up constraints against this layout guide to position all of your content within the safe area.
Now, if you're performing layout manually, you may actually just want to read the current safe area values for a particular point in time.
And you can do that with the safeAreaInsets property.
Now, this is in the coordinate space of your view, so it's really easy to use to position your content exactly where you want.
Now, of course, if you're doing manual layout, you'll also need to know when that changes.
And so, you can override the safeAreaInsetsDidChange property to find out when it changes and adjust your layout.
Now, there's a lot of things, because this is integrated throughout UIKit, that could be handled automatically for you, that previously would have been more difficult.
For instance, UIScrollView can automatically include the safeAreaInsets as additional scrollable padding at the top and bottom of your views.
So, that even if they're underlapping the bars, you can be sure that your content can always be scrolled into view.
Now, in previous releases, UINavigationController tried to handle some of this on your behalf by calculating the overlap of the bars.
And then, setting a value on the contentInset property for your UIScrollView.
Now, you may have noticed that if you ever tried to set your own contentInset for the UIScrollView, because you'd end up fighting with NavigationController over who owned that current value at a given time.
In iOS 11, that conflict is gone, because UINavigationController no longer has to set the contentInset property.
ScrollView can set it on its own behalf, by just looking at the safeAreaInsets, leaving the actual value of contentInset to be owned by you, for your application needs.
[ Applause ]
So, UIScrollView tries to do the right thing, automatically, as much as possible for this case.
But it's not always possible, of course, to get it right 100% of the time.
And we know some of your apps have different needs.
So, to help make sure that you can always have the right behavior, we have a new property on UIScrollView that gives you full control over how ScrollView interprets these safeAreaInsets.
So, with this, you can tell it whether it should automatically apply the insets, or just ignore them, entirely.
So, that you can do the right thing for your app, if it happens to be the case that the automatic behavior isn't exactly what you want.
And if you want to find out exactly what has happened, as far as the ScrollView is concerned, you can look at one new property that can give you the current value of what it has computed from safeAreaInsets, plus the sum of an contentInsets that you have set, yourself with the adjustedContentInset property.
So, you can find out exactly how much space the ScrollView thinks it needs to have for scrollable padding.
So, so far, we've focused a lot on bars.
But there's also some other refinements to other parts of the UI, as well.
You'll find that UITableViews across the system, how have a new unified swipe delete implementation that feels just like what you're used to from the Mail app.
It includes support for multiple actions on both the left and right swipes, as well as single gesture activation of the default one, with a full gesture across the entire TableView.
It's also really easy to use in your apps, as well.
So, with the new UIContextualAction class, you can specify the actions that you want to be able to display in the TableView's rows.
Just providing the style that you'd like them to appear with, and the title of the action, and a block to invoke when they should be run.
And then, with the new UISwipeActionConfiguration class, you can group together multiple of these contextual actions to display on the left and right side of individual rows.
And you can also specify whether the first one should automatically be invoked when a full gesture occurs across the entire row.
Yeah, it's very cool.
[ Applause ]
We do actually use this, now, across the system.
You'll find more actions in many more places than before.
But do keep in mind, though, when you're using it, that any actions that you put in the rows behind the swipe actions will be hard to discover than something's that's visually prominent in your application.
So, definitely use it as an accelerator, but probably don't make it the only way to perform a particular action.
So, outside of that, we've also given you more control over the placement of separators in your UITableView.
So, there's a new property on UITableView that lets you control how separatorInsets that you set on the TableView are interpreted.
You can indicate that they are absolute values so they're relative from the edge of the cell.
Or you can indicate that they're meant to be deltas, offset from where the TableView would have otherwise placed the separatorInsets had you not specified anything.
This makes it a lot easier to make sure that your separators end at exactly where you want them.
Regardless of the device that you're running on or the size class that you're currently running in.
[ Applause ]
So, there's a ton of new UI refinements.
And there's a whole session that can tell you about this and many more.
It's the Updating Your App for iOS 11 session.
So, you should definitely check that out.
And to give you some ideas on the thinking behind the design of some of these new updates and how you can best integrate them into your apps, definitely also, check out the design session, Design Studio Shorts 2, later this week, as well.
So, with that, I'll hand things back to Eliza to tell you about some more API enhancements around Cocoa Touch.
[ Applause ]
I'd like to start with some of the new APIs in Swift 4 and Foundation.
So, there's actually a lot of really exciting additions to Swift 4.
And I'm only going to cover two things, now.
The first is archiving Swift native types.
So, if you've attempted to use Swift 4 native types like enumerations and structs with code that needs to participate in, for example, NSCoding, you'll have found that this has been historically quite difficult to do.
Swift 4 solves that problem with the introduction of a new Codable protocol.
And as long as the underlying types in your enumerations and structs, are themselves codable, all you have to do to adopt this is declare conformance to the protocol.
And then, Swift handles the rest.
So, that allows these native types to participate easily in NSCoding.
And Foundation has also added support for archiving to JSON and property lists.
Another really exciting edition to Swift 4 is the new KeyPath type, and a literal syntax, and getters and setters that correspond to it.
So, in the past, you specified KeyPaths by hardcoding a String in your code, which as a result, couldn't be, if you had a typo in it, it wouldn't be found at compile time.
Now, there's a new literal syntax, this /, that allows you to construct a KeyPath, and this is a strongly typed object.
So, if I have a presenter object, for example, that has a couple properties, a copresenter, which is another presenter, and a name.
I can construct a KeyPath object representing my copresenter's name.
And then, I can use this new square bracket getter notation to access that property on one of my presenter objects.
So, in this case, accessing it on an object representing me would return the String Josh.
You can also forego making the KeyPath object as a separate step and just use the literal syntax in the getter.
And take advantage of Swift's type inference, to leave off the type, if you do it that way.
So, this is very cool.
And Foundation has taken it one step further by introducing an updated way of using KVO with these KeyPaths.
So, this is a picture of what you used to have to do to observe changes to a property on one of your objects.
It was a little bit involved.
You had to override a method.
And because your Superclass might also override that method, you had to use a context pointer to disambiguate which one of you is getting it at any given time.
And it was quite difficult to get right.
So, new in iOS 11, we have block-based KVO.
We're really excited about it.
[ Applause ]
If I want to observe the changes to my copresenter, I'm not sure why I would, since it never seems to change, I can do so by simply setting a block and observing one of these KeyPaths using a literal syntax.
So, that's very cool.
There's a lot of new topics in Foundation.
And please check out their related session, on Wednesday.
Okay, deferring system gestures.
And this is a funny case.
So, if you have an app that maybe, shows some content, and shows its status bar, the user can swipe down from the top to bring in the notification center.
However, if you hid your status bar and the user swipes down from the top, they'll instead see this tab UI.
And in that case, your app will actually receive the touches that are originating near the top of the screen.
Now, we did this in iOS 5, when we introduced the Notification Center.
Because we wanted to make sure that apps that might need to see touches near the edges of the screen, could do so.
And we took the presence or absence of the status bar as an indication of whether your app fell in that category.
So, then in iOS 7, we introduced the Control Center with a swipe up from the bottom.
If your app hid its status bar, we used the same rule and we would show the tab instead of the control center.
Now, that made a little bit less sense, because the status bar is at the top of the screen, not the bottom.
And so, the presence or absence of the status bar shouldn't really tell us very much about what your app needs to see, in terms of touches near the bottom.
So, the other problem with the status quo, here, is that your users really want, when they swipe near the edge of the screen, to see the system UIs components appear.
That's what they expect to have happen.
So, unless your app actually needs to get access to the touches near the edge, it's a better user experience to allow those notifications that are in Control Center to simply appear right away.
So, in iOS 11, we're allowing you to make this explicit by adding this new preferredScreenEdgesForDeferring System Gestures method.
If you override it in your viewControllers, you can return a UIRectEdge, which is a collection of different edges.
And we strongly encourage you to only return edges that you want to protect from system gestures.
If you really need to see touches that are right on that edge of the screen.
Because it will be a better experience for you users to just allow the system gestures to happen as they normally would.
So, another topic where we've made some improvements, is Auto Layout.
And in particular, the interaction of Auto Layout and Scroll Views.
So, Scroll Views pose kind of a challenge for Auto Layout, because they represent two different coordinate systems mushed into one.
You have the frame of the Scroll View, and then, you have the coordinate system of its content.
Which is often larger than the Scroll View, and is almost always offset relative to the Scroll View's origin.
So, when you're composing your constraints for Scroll Views, Scroll View has a lot of know-how kind of built in, where it guesses what you probably meant.
And it tries to do the right thing based on the constraints that you're composing.
But in iOS 11, we're allowing you to make it really clear what you mean and be completely explicit about it, by introducing two new Layout guides on Scroll View.
A contentLayoutGuide and a frameLayoutGuide.
So, now you can construct constraints that specifically represent one of these coordinate systems or the other.
[ Applause ]
So, this allows you to do something really easily, that used to be hard.
So, sometimes when you have a Scroll View and you have content that can zoom in and out.
You want the content to come to rest in the center of the Scroll View as you're zooming out on it.
Now, Josh and I, a couple of years ago, spent one-third of the WWDC presentation explaining how you could get this effect in your Scroll Views.
And up until recently, it was actually really hard to do it with Auto Layout.
But now, you can do it in two lines of code.
All you need to do is set the centerXAnchor of the imageView, or whatever the content of your Scroll View is, equal to the contentLayoutGuide's centerXAnchor.
And then, you would do the same thing in the Y coordinate.
And then, this will just happen.
[ Applause ]
So, Dynamic Type.
Now, dynamic type is a really important feature on iOS.
And here's a picture of a whole bunch of different dynamic type sizes that the user may configure, and how we're handling it in our own Calendar app.
So, here's a small setting for dynamic type.
And there even are larger accessibility dynamic type sizes that can be selected.
So, this can pose a challenge in a number of ways to support in your applications.
But for users who have chosen a nonstandard dynamic type size, it's a really bad user experience if your app doesn't participate or honor their selection.
So, we've made a few improvements to make it easier to do this correctly in your applications.
And the first one has to do with sizing your text.
So, suppose you have a 16-point font that you're using for the standard type size.
How do you decide what font to use if the user has a nonstandard dynamic type selection?
The old way of doing this was you could ask UIFont for the preferred font for a given text style, which.
And there's a number of text styles, Body, Title, a variety of them you can look up.
And this was pretty good, because it would get you a good font for the appropriate place in your application.
But it was a little inflexible, because what if you needed a custom font?
This is just going to give you the system font, every time.
What if you wanted to use a Monospace Number font in some particular case?
Or just some font that, you know, matched your branding a little bit better.
In iOS 11, we're introducing a new class that solves this problem, called UIFontMetrics.
And the way you use it, is you create a FontMetrics object for the text style that you're interested in.
You then, choose any font you want, sized for the standard dynamic type size.
And then, you can ask the FontMetrics object to scale that font given the user's current settings.
And that gets you back a font, any font you want, at the appropriate size to display.
Yeah, this is really cool.
So, just that, alone, doesn't completely solve the problem, because imagine you have like a custom button, or maybe a custom bar.
And you're putting some text inside it.
How tall do you want to make that button?
If the user has a nonstandard dynamic type setting, it might overrun the height that you've made available.
So, UIFontMetrics has solved this problem, as well, by allowing you to scale arbitrary layout values.
So, you create, once again, a FontMetrics object.
You choose a height that would look good at the standard dynamic type size, and then you can scale it based on the user's current settings.
So, this is super useful for your font sizing and layout.
Now, we also have an addition to Auto Layout to support dynamic type, which we're pretty excited about.
Suppose that I have two labels with different fonts, maybe, laid out vertically.
And I've chosen a baseline to baseline spacing that looks good at this font size.
Now, my user might have chosen a larger or a smaller dynamic type size.
And as a result, the spacing might actually look quite a bit too tight or too loose.
So, with Auto Layout, there's now a solution for this problem, which is that we're exposing a way to access the system recommended spacing.
And you do this by, first of all, there's two ingredients.
You need to be doing baseline to baseline spacing, in order to inform Auto Layout that it should take font sizes into consideration.
So, I would make a topAnchor using the lastBaselineAnchor of my topLabel, and a bottomAnchor using the firstBaselineAnchor of my bottomLabel.
And then, I would use the new constraintEqualToSystemSpacing below method to ask Auto Layout to choose a value that will look good, given the font sizes that are being displayed.
And that will cause the text to adjust, so that's it's visually pleasing at all of the different dynamic type sizes.
And this works with the Visual Format Language, as well.
Again, we have the same two ingredients.
We have the system spacing, which is provided by the dashes in my Visual Format String, and then, a new baseline to baseline option to pass.
So, that the Auto Layout system will know to do this work for you.
And it also works with UIStackView, again, passing those same two options.
So, to find out more about building your apps with dynamic type, please check out this associated session, on Friday.
A lot of good content, here.
This is my very favorite new API, that we're introducing, this year.
I'm really excited about it.
Some of you may have experienced a workflow similar to this.
This is my standard workflow when I sign up for a web service.
I sign up for the web service of some kind.
I allow Safari to suggest a password, which I dutifully accept.
It's a nice strong password that I would never want type in a million years.
Then, the service says, ''Hey, download our app.'' And so, I do.
I launch the app, and I'm immediately presented with this password entry field.
And of course, I've saved this strong password in my iCloud Keychain.
So, I don't know it.
So, I'm completely stuck.
So, I go back to the web interface, and I say I forgot my password.
And I reset the password to something really easy like Password.
And now, I go in and I log in and I've got no security.
And I probably get hacked.
It's a disaster.
So, starting with iOS 11, this nightmare is going to end.
We are introducing a really great new feature, where when we detect that you're showing a username and password field, this key UI will appear in the candidate bar.
And if you click on it you get a list of all of your saved passwords in the iCloud Keychain.
And you can go through and select the right one.
Now, that already is a better experience than the one where you're completely stuck.
But it's not ideal.
For a lot of users, they're not really going to know what to do with this list.
If you're like me, you have a lot of passwords on this list.
And scrolling through it to find the right one might be a little bit challenging.
So, there's a way that you can make an even better experience for your users, here.
Which is just a couple steps.
So, we what we want is for the correct suggestion to appear in the candidate bar, by default.
And then, you don't even need to mess around with finding the right value in that list.
And to do that, it's just two things.
You have to add one entitlement to your application, and a couple of lines of JSON to your web service.
And you might have already done these steps to support universal links.
So, if you have done that, then this really good UI will appear.
And when I tap on it, I simply get my password filled in.
So, please for my sake, adopt this in your apps.
We're really excited about it.
And go to the associated session, tomorrow.
[ Applause ]
There's a couple of improvements to Asset Catalogs that we're excited to tell you about.
Colors can now be added to Asset Catalogs, as well as icons.
So, you can now make named colors.
[ Applause ]
And this allows you to easily support wide gamut colors on the appropriate devices.
So, you can create a wide gamut color and add it to your Asset Catalog.
You can access it by name.
And you can also, make a fallback color to be used in the sRGB Color Space for devices that don't support wide gamut.
And you can now, do the same thing with your app icons.
So, app icons can now include wide gamut colors, which will be displayed on devices that support the P3 Color Space.
In addition, you may find that, well, at least it's true for certain apps, that the icons are actually the largest aspect of your app's footprint.
And so, by incorporating them in Asset Catalogs, we're now able to have them participate in the app thinning, which will significantly lower your app's footprint.
So, this is a really exciting thing to adopt, and it will be adopted by default in new projects in iOS 11.
You can opt into it in existing projects by adding a key to your Info.plist.
So, PDF-backed images.
These are something that have been possible for a little while, now.
But there's a new option when you add an image to your Asset Catalog, that's PDF-backed.
You're given the option to preserve the vector data.
So, this is new in iOS 11.
And it's a really powerful feature.
If you click that box, the vector data will be shipped with your application.
Which, on the one hand, makes your application a little bit larger, because the vector data takes up some space.
But on the other hand, will give you the opportunity to scale these images, which might be useful in a number of different situations.
So, one is, if you know that this particular image is going to be used at multiple sizes.
But that might be less obvious.
So, one case is a symbolic glyph that should resize with dynamic type.
Since we're thinking about dynamic type, you should also be thinking about having glyphs that are appearing next to type resize appropriately.
Another case that's really not obvious, is tab bar images.
So, you're probably used to your tab bar images appearing at just a single size.
But there's a really great accessibility feature that we strongly recommend supporting, that allows for user that have turned their dynamic type size up.
When they tap and hold on a tab bar image, a larger version appears in the center of the screen in a Hud.
And as you swipe your finger you can see different ones.
So, you can support this in your apps by returning a different image to use for this purpose.
But if you use PDF-backed images and preserve the vector data for your tab bar images, it will just happen by default.
So, we really recommend doing that to increase the usability of your app across all users.
And the final topic that I want to discuss, is ProMotion.
So, as you heard, on certain new iPads we're increasing the refresh rate of the screen.
And you can find out what the screen's refresh rate is on a particular device, by querying this property on UIScreen.
So, once you've queried it, what should you do with that information?
Well, it depends on what kind of app you're building.
So, if you have a UIKit application, the answer is actually you really shouldn't do much with this.
The crucial thing for a UIKit application, is you just want to optimize your drawing code.
You just want to make sure that you're getting your frame rate as high as you can on all devices.
And to do that, we strongly recommend using Instruments.
You can check out the frame rate that you're achieving during scrolling and animations.
And find out what might be bogging you down.
And if you do that, then it will really improve the user experience on your app across all devices, including ones with a higher screen refresh rate.
The situation is more complicated for Metal apps.
So, for apps that are using Metal, you're going to want to think more about what refresh rates to try to hit in different situations.
So, your goal here, is to ensure smooth playback.
And in the past, you might have been actually pessimistically clamping your refresh rate to 30 frames per second to make sure that the frame rate is smooth.
But now, on devices that support higher screen refresh rates, you could, for example, clamp to 40 frames per second to get a better smooth playback experience, since 40 divides evenly into 120 frames per second.
If you're showing cinematic content, you might want to choose a refresh rate of 24 frames per second, which now also, will look really smooth on these devices.
So, a lot of options, here.
You probably want to think about the content that you're displaying to conserve power.
You don't want to be hitting 120 fps all the time.
And finally, you can use XCode's GPU Report feature to look at the performance characteristics of your Metal applications.
There is a session on Introducing Metal 2, that we strongly recommend going to.
And that's what's new.
So, I'm going to hand it back over to Josh.
Thanks, very much.
[ Applause ]
We got a late start, this morning.
So, we're going to have a really quick end, right now.
I have one last topic I wanted to talk about, really quickly, and I promise this is really quick.
So, Localization is a really key way to broaden the reach of your apps.
And for many people, Localization can seem synonymous with translation.
But it's actually more than that.
And one quick thing I just want to mention is considering layouts that are important for localized applications.
So, take a look at this, really quickly.
For many of you, this probably feels really comfortable.
But if you now, keep watching.
I'm going to change it, and hopefully, make you feel kind of uncomfortable.
Now, this probably seems really backwards.
Labels are aligned weird, arrows are in the wrong direction, animations happen the wrong way.
But believe it or not, this is actually a real layout.
You just don't usually see it with English.
You usually see it with a language that reads right to left, like Arabic or Hebrew.
Now, for a user that expects to see this, this feels really natural.
So, if you felt comfortable with this and uncomfortable with this.
Then, now you know what someone whose native language reads right to left feels like if they're not presented with this.
Now, you want to make sure if you're localizing, that you also support RTL in your layouts, if you're going to support RTL languages.
Because the system is doing this all over the place.
Many teams have been spending a lot of time to make sure that this is right.
And in fact, UIKit does a lot of it for you.
So, navigation controllers and switches will switch automatically.
But if you're building your own custom views, you definitely want to take a look at your layouts in RTL languages, as well, if you localize in those languages.
So, that was my really quick wrap-up on that.
Lots more information about localization in the Localization Guide on developer.apple.com.
And of course, there's plenty more info available from this session, and a ton of related sessions, all week.
The four Drag and Drop sessions are going to be great.
You definitely should check them out.
Updating Your App for iOS 11 is really going to be a great session, as well.
And make Eliza happy and go check out the Introducing Password Autofill for Your Apps.
And implement that.
Thanks, very much.
And enjoy the week.
[ Applause ]