WWDC2018 Session 202

Transcript

[ Music ]
[ Applause ]
>> Alright, good morning.
Thanks so much for coming out
this morning to learn all about
what's new in Cocoa Touch.
Now normally, Eliza would join
me up here a little bit later
although this year actually
you're just going to be hearing
from me.
So, she'll be back in later
years.
Don't worry about it.
This morning we're going to talk
about things in three main
categories.
We're going to start with some
framework updates including
things like performance and
security.
Then we're going to talk about
some API enhancements across a
number of different existing
APIs in the SDK, including
notifications and messages.
And then we're going to end with
Siri Shortcuts.
So let's get started with our
first topic: Performance
Updates.
Now we're going to talk about
performance across three main
areas: scrolling, memory, and
auto layout.
Now before we get in to it, it's
important to keep in mind one
little bit of background
information about scrolling.
Scrolling on iOS follows a
pretty common pattern in most
places.
We load content to be displayed
into the views and then we're
just moving that content around.
And while we're moving it
around, most of those frames are
really cheap to generate because
we don't have to load anything
new.
But every now and then, a new
view first becomes visible and
the one frame when that first
happens is quite a bit more
expensive to generate than those
other cheaper ones.
Now, of course, once that one
frame is loaded, we're just back
to moving content around, so the
amount of work we do on the CPU
goes back to being pretty small
for most of that other
scrolling.
So what's happening during that
really expensive frame that
causes that one to be more than
all the others?
Well, let's take a look from the
perspective UI Table View but
everything we look at here will
really be the same for UI
Collection View or really any of
your own custom views that you
may build that behave in similar
ways.
So the work in that expensive
frame probably starts in your
implementation of TableView,
cell For Row At index Path
delegate method.
Now the first thing we're going
to do in there is get the cell
that we want to display.
And so we're going to try and
dequeue it ideally from the
reuse queue although if one is
not available already in the
queue, we might actually have to
do some memory allocation in
order to get it ready.
Once we have the cell, we're
then going to populate it with
your model data.
Now how expensive that is will
vary depending on your
application but it can be
including a fairly large amount
of expensive operations like
reading files, loading data out
of databases, or other things of
that nature.
So you'll definitely want to
look at the expense here in your
own apps but it tends to be this
is where a good portion of it
will exist.
Now, you may think looking here
that that's the end of the
expensive work but even once you
return from this method, there's
actually more work that has to
happen in order to get the cell
prepared to have it show up on
screen.
So, of course, next, we have to
lay out all of the content in
that cell.
We need to size all the views
and position them in the right
spot.
Now, this can actually be a
pretty substantial amount of the
total time that we're spending
because it can include other
expensive operations like
measuring text.
Once everything is properly
sized and positioned, then it's
time to generate any content
that would need to be drawn
using drawing calls and to do
that we have to call draw Rect
on all of the subviews within
that cell.
Again, this can be a pretty
large amount of the time because
we'll also be doing things like
drawing text.
So overall, there's a lot of
work that has to happen across
this whole piece of code and it
has to happen in a really short
period of time.
On our 60-hertz devices, you
have 16 milliseconds to complete
all this work in order to make
sure you don't drop any frames,
and maintain smooth scrolling.
On our 12-hertz iPads, on the
iPad Pro, you have only 8
milliseconds to complete all of
that work.
So, it really needs to be done
as quickly as possible.
Now, to help with that, in iOS
10, we introduced a cell
prefetching API and the idea
with the prefetch API is to take
some of this work, populating
your cell with model data, and
pull it out of this critical
section that's happening on
demand in that short window, do
it earlier, and do it on a
background thread so it can
happen asynchronously with some
of the other work, in particular
those cheaper scrolling frames
we talked about.
Now adopting this is really
easy.
It's just a UI Table View Data
Source Prefetching protocol and
it only has two methods, only
one of which is actually
required.
And the idea here is to move
some of that expensive work of
loading things from files or
reading your database into here
so that you don't have to do it
on demand.
You data is already prepared
when the cell is needed for
display.
So this in most cases can be a
really big win although while we
were looking at some of our own
apps in iOS 12, we actually
noticed a case where this was
causing an issue instead of
helping us.
So let's take a look at what
that looked like.
Now here's an example of a trace
that we took while scrolling on
an iPhone 6 Plus.
The vertical bars across the
top, those represent frames that
we want to display.
The alternating light and dark
blue colors represent frames
that we did swap to the display
as they were changing.
And that double wide light blue
bar, that is a place where we
drew the same frame for two full
frame durations.
So for a customer looking at the
device while this was happening,
that looked like a dropped frame
or a scrolling hitch, which
obviously is what we're trying
to avoid.
So what was happening in this
case?
Well, here you can see that red
bar is representing the time
that we're spending in the
critical section we just talked
about, all the self-[inaudible]
index path, layout, and drawing.
And here, it's actually taking
longer than the 16 milliseconds
we had to draw the frame.
Now because the device can only
swap new frames onto the screen
at fixed positions in time, once
we miss that deadline, we ended
up displaying the same frame for
two full durations, which was
obviously not great.
So why did that happen here?
In this case, we're looking at
an app where we actually had
implemented the cell prefetching
method so our data should've
been ready.
Ideally, this could've been done
more quickly.
Well, if we look at a little
more of the trace, we can see
what was going on.
The cell prefetching API was
being called at the same time
that we were requesting the
current cell.
Now it wasn't being called for
the data for the current cell.
It was being called for data
that we might need in a future
cell, but it was getting run at
the same time.
And so there was now contention
for the CPU as we tried to both
load the current frame and also
load data for a future frame
that we don't actually need yet.
So because of that contention,
it actually caused both tasks to
take a little bit longer.
Now in iOS 12, we're much more
intelligent about scheduling
these background prefetch
operations so that rather than
happening concurrently and
causing some CPU contention,
they'll now happen serially,
shortening the time that you
need to take to load the current
cell and helping avoid dropped
frames in many cases.
[ Applause ]
So once we had that fixed, we
kept profiling our apps and we
actually found another case
where there was a bit of a
surprising cause of some dropped
frames.
Now what we found was that when
the device was not under load,
there was no background
activity, all we were doing was
a little bit of scrolling in the
foreground app.
Counterintuitively, we could
actually drop more frames than
times when there was some small
amount of light background work
going on.
That didn't really make a lot of
sense.
And to understand why it was
happening, we had to drop down a
level and take a look at the
behavior of the CPU when it was
scheduling our workloads.
So let's take a look at another
trace.
Here, we've got the same
situation.
Double wide blue bar is causing
us to drop a frame or rather is
our dropped frame.
Now here we can see a graph of
our CPU's performance over time.
Now during most of those cheap
frames, our CPU performance is
staying pretty low.
There's no background work going
on.
All we're doing is scrolling
things and that's exactly what
you would want because when
we're not doing expensive work
for scrolling, you want to keep
the CPU as low as possible to
preserve battery life.
So that was great.
What wasn't great is that it
took a little bit of time before
it could ramp up.
You heard about this yesterday
in the keynote.
Now when it did finally ramp up,
it was already too late to have
completed the work to load the
cell that we needed to display
and so we ended up missing that
frame again.
Now because we own the full
software stack from top to
bottom, in iOS 12 we took all
the information we have in the
high-level UIKit framework about
what scrolling is happening and
when these critical sections are
occurring and pass that
information all the way down to
the low-level CPU performance
controller so that it can now
much more intelligently reason
about the work that's happening
and predict both when these
bursts will occur and how much
CPU performance will be required
to meet the deadline for the
historical demand that your app
has had.
So once that change happens,
where the load starts right
here, we end up seeing that
we've ramped the CPU far more
frequently or, far more quickly,
to the exact amount of perform
it needs to make sure that we
hit that deadline and don't drop
frames.
This has caused a really great
improvement across many
different scrolling scenarios
around iOS.
So all of your applications will
get all of this enhancements,
both of them and a number of
others, for free with no
additional work on your part,
but there are a couple of things
that you can do to make sure
that you get the most out of
both of them.
So first of all, if you haven't
already adopted that tableView
cell prefetching API or the
Collection View one, definitely
look into that because having
your data ready is one of the
best things you can do to make
sure that loading cells is as
quick as possible.
Of course, it's also important
that you profile your full
critical sections of your cell
loading and reduce that demand
as much as you can.
iOS 12 will now try to match the
CPU performance to the needs of
your application during this
period but the best thing that
you can do will always remain to
reduce the amount of work that
you have to do to make sure that
you give your customers a really
smooth scrolling experience.
So that's scrolling in iOS 12.
Next, let's turn our attention
to our next performance topic:
memory.
Now, you might wonder why memory
is showing up right here in the
middle of a performance
discussion, but I assure you
that that actually makes a lot
of sense and, in fact, the
reason is because memory really
is performance.
The more memory that your app is
going to use, the more that it
will have an impact on the
performance of your application.
So to understand why, let's take
a look at a really high-level
overview of what the overall
memory on the system might look
like in a common situation.
So, of course, you can see here,
a lot of the system's memory is
being used by other applications
and the system itself.
Your app is using some amount
for the moment.
And there's some that's being
kept free to service new
allocation requests as they come
in.
Now, most of that memory is
probably not truly free.
It's likely including things
like caches or other things that
can be quickly thrown away to
make sure that the memory is
available to satisfy demand
right away but in general it's
probably actually being used for
something, but it is readily
available.
So let's look at what happens
when your application requests
some memory.
Maybe you'll make a small
request, something that can be
satisfied by the amount that's
currently available in that free
pool.
Well, if that's the case, it'll
be return right away to your app
and you can continue on with
your work.
Now, let's say, though, that
your application makes a larger
request, and maybe it doesn't
need it for a long period of
time, so you might not be real
worried about it.
Perhaps you're just going to
load an image off disc and
decompress it, perform some
quick operation on some of the
pixels and then throw it away.
So it seems like a quick
operation that you don't have to
worry too much about.
Well, we'll make that big
request and now that is more
memory that is currently easily
readily available to the system.
So it won't be able to satisfy
it immediately and we'll have to
go find that memory from
somewhere else.
And, in fact, the most likely
place to come from is from other
applications or things on the
system.
Now, that might not worry you
too much because you're trying
to get the memory for your app
right now, so you're not so
worried about what's happening
elsewhere.
But, of course, this will have
an impact on something else
later that your customers will
be expecting will be working,
but more importantly to you
right now, it will have an
impact on your app as well
because the system has to do
work to go get this memory for
you.
The fact that it's not readily
available means that the kernel
has to go find it and perform
operations on the CPU in order
to make it available.
And that time it's spending
getting that memory for you is
time that could be better spent
doing whatever your app does
best.
So finding ways to either chunk
these larger requests or just
reduce those overall peak
demands can actually have both a
big impact on the performance of
your app while you're using it
and also improve the customer
experience across other apps
later.
So there's many ways that you
can reduce the total memory
usage of your apps and starting
with a profile and instruments
is a great way to look at that.
But for this morning, we're just
going to take a look at one new
technique that iOS 12 brings
along that helps reduce the
memory usage of your apps and
that's Automatic Backing Stores.
So let's say we want to draw
this lazy prairie dog in
portrait mode on an iPhone X.
Now, how big is that going to
be?
Portrait mode on iPhone X, 375
points wide and, to preserve our
aspect ratio, it'll be 250
points tall.
So how much memory will that
use?
Well, 375 by 250 at 3x, with 64
bits per pixel because this is a
deep color device, is going to
be 2.2 megabytes of memory to
draw a prairie dog.
That seems like a pretty decent
amount, but in this case that's
actually probably memory well
spent.
We're actually trying to
represent this full-fidelity
image and that's the amount of
memory that's needed to draw it
into this buffer.
So that's probably expected.
But now let's say that we were
going to draw a lower-fidelity
version of our prairie dog,
maybe something in black and
white that we were going to
sketch out with core graphics,
maybe it was drawn with an Apple
pencil on an iPad.
That might look something like
this.
So how much memory is our
low-fidelity prairie dog going
to use?
Well, it'll actually use the
exact same amount of memory.
Now here, that clearly is not as
good of a use of memory.
It's all grayscale.
All of that deep color
information is not even being
used in this image.
So hopefully we could do much
better and iOS 12 introduces
automatic backing store support
to help make that exactly be the
case.
So all of your views now that
implement draw Rect will have
their backing stores defined by
the depth of the content being
drawn into them.
So in this case where we're
using Core Graphics to sketch
out only grayscale content will
actually automatically use an
8-bit per pixel backing store
instead of a 64-bit per pixel
one.
This reduces the memory demand
for that drawn view by an order
of magnitude down to 275
kilobytes from 2.2 megabytes.
That's a really big improvement
across many different
applications, both yours and
ours.
[ Applause ]
So Automatic Backing Stores are
enabled by default for all apps
built with the iOS 12 SDK.
All implementations of draw Rect
on UIView will have this happen
automatically as well as all
content that you draw with UI
Graphics Image Renderer into
offscreen bitmaps.
Now in the case of UI Graphics
Image Renderer, we don't
necessarily know what you're
planning on doing with the image
that you get out at the end.
So in cases where you actually
know that the automatic behavior
is not what you want, from Image
Renderer, you can specify the
specific backing store style
that you want, for example using
the new Range API to specify
specifically that you want an
extended-range image.
Now you can learn all about this
and many more techniques around
UI Image in the Images and
Graphics Best Practices Session
later this week.
So that's our second top for
performance.
Next, let's move on to Auto
Layout.
Now Auto Layout in iOS 10 has
some really great improvements.
The team has been working
incredibly hard to optimize Auto
Layout for your apps as much as
possible.
So you'll find that Auto Layout
is now faster by default in iOS
12.
We'll talk about a number of
ways that's the case.
But while they were profiling
and optimizing Auto Layout, they
also were looking across the
system at many of our own apps
and how they were using Auto
Layout and they found a number
of cases where there were some
common pitfalls that different
apps were falling in to.
So we'll show you some of the
simple best practices that you
can follow in order to optimize
your app layout as well.
So this morning, though, let's
look at how Auto Layout is
faster by default in iOS 12 by
looking at the asymptotic
behavior of Auto Layout as we
add more views in some common
user scenarios.
Now, we're looking at the
asymptotics because we really
want to look at what happens as
we dramatically increase the
number of views.
This can really make performance
issues show up quickly when we
go to a really like absurdly
large number of views.
That just helps us see it
though.
The optimizations really do
apply and make things faster
even for small numbers of views.
So let's start with a really
common pattern, the simplest
case really, Independent Sibling
Views inside of some container.
Now, these views are positioned
with constraints against the
container or other views but not
against each other.
They're independent of one
another.
Now in iOS 11, the cost of these
independent siblings, as you
continue to add more, grew
linearly.
So that's actually pretty great.
That's exactly what you'd expect
for a situation like this.
Basically, what we're saying is
that there's a fixed constant
cost for each additional new
view that you added into your
hierarchy that was positioned
independent of those other
views.
Now because that was already
growing with the exponentials
that we expected, that remains
the case in iOS 12; however, the
team has worked really hard to
reduce that constant cost to
make additional views as cheap
to add as possible.
So let's look at a more
interesting example next.
And in this case, we're going to
take a look at Dependent
Siblings.
So this is the case where you
have multiple child views and
they're now, they have
constraints between each other.
So their layout is dependent on
one another.
Now, unfortunately, in iOS 11,
you'll find that the asymptotics
here weren't quite as nice.
In fact, it was growing
exponentially.
So the more views that you
added, the surprisingly larger
cost you would find as you added
additional ones.
Now, the team worked really hard
to identify the source of this
exponential growth and fixed the
algorithm so that is no longer
the case.
So on iOS 12, these now grow
linearly.
[ Applause ]
And, of course, the team's also
been working to reduce those
constant costs for these cases
as well.
Now in addition to dependent
siblings, there's another common
type of layout that you'll find
and that's Nested Views, when
one view is inside of another
and there's constraints out to
those outer ones.
This is obviously also a pretty
common pattern in your apps and,
unfortunately, here as well in
iOS 11, we found some
exponential growth.
And again, great news.
The team has also made this
linear in iOS 12 as well.
[ Applause ]
So there's a number of really
great improvements across Auto
Layout in iOS 12 and you'll see
these improvements in your apps
as soon as you start running
them on iOS 12 yourselves.
To learn more about all of that,
get a better sense, develop a
good sense of how to get some
gut feel for the performance of
different layouts and here are
some of these topics I was
talking about that are common
pitfalls.
Definitely check out the High
Performance Auto Layout talk
later this week.
So for our final framework
update topic, let's turn to
Swiftification.
As you heard, iOS 12 introduces
Swift 4.2.
And for Swift 4.2 we really
wanted to make sure that UIKit
had a really great feel when
used in Swift across your app,
especially where it interacted
with other Swift Standard
Library or places that Swift had
common patterns.
So, we audited all of UIKit and
made sure that everything feels
like it fits really naturally.
Even better, we made sure that
all of the changes that we made
to UIKit are all automatically
migratable so there's no
additional work that you should
have to do in order to get these
updates.
Now, these updates fall into
really three categories that
we'll talk about this morning,
although there's actually a ton
of improvements and consistency
improvements that you'll find as
you look at the SDK.
But today we'll talk about
nesting of types, constants, and
functions.
So let's first look at nesting
types.
Now in Swift 4, there were a
number of types that were in the
global name space, things like
UI Application State.
For types like this that have a
really strong use along with
another class, we've now nested
them within this class.
So we looked at all the
enumerations and other global
types of this sort and now have
moved them to be child types of
the relevant class.
So this becomes
UIApplication.State.
This sends a much stronger
message about the relationship
between these two and makes them
easier to find as well.
Now in comes cases this can also
help improve understandability
and remove some confusion.
So in this case, let's look at
UI Tab Bar Item Positioning.
Now do you think that's
UITabBarItemPositioning or
UITabBarItem Positioning?
It could actually be either.
Those are both classes.
And in Swift 42, it is now
perfectly clear that it is, in
fact, UITabBar ItemPositioning.
So in addition to nested types,
we've also nested a bunch of
constants.
So if we look here at Swift 4,
we had NS notifications were all
in the global
NSNotification.Name namespace
and their associated user info
keys were actually just global
constants that were floating out
there.
So for consistency with AppKit
and to make it easier to find
and associate these types
together, they've now all been
nested under the class that
they're used with.
So something like did Change
Status Bar Orientation is now
under UI Application did Change
Status Bar Orientation
Notification and its user info
key moved along with it so that
they're all co-located.
Now we've also audited all of
the other global constants all
throughout UIKit and nested all
of them in appropriate places.
So things like UI Float Range
Zero and UI Float Range Infinite
have not just become properties
on UI Float Range so they're
both easy to find and easier to
use.
In places to take a UI Float
Range, you can now just type
.zero or .infinite and, in fact,
because they're now properties,
Xcode can suggest them as
auto-completions for you in
places where they make sense.
Now in addition to constants,
we've also audited all of our
global functions.
So things like UI Edge Inserts
and UI Image had some global
functions for operating on
different types.
Now in Swift 4.2, these had
become methods on the
appropriate type.
So it's now really easy to inset
Rect or get png Data from an
image in a really natural Swift
feeling way.
[ Applause ]
Now, here was one other big
class of functions that I want
to mention this morning and that
was all of these string
conversion functions for all of
the many types in UIKit,
CGPoint, CGRect, CGSize,
CGVector, all of them, there's
quite a lot, both to and from
strings.
Now, when we looked at these and
tried to decide where they
should go, we realized that they
actually have two different use
cases.
One is for encoding and
decoding.
But the other is that they're
commonly used to print things
when you're just trying to get
some debug descriptions.
And those are two very different
uses but, in fact, Swift has
first-class support for both of
those cases.
And so we've made sure that all
of these types will work really
great with Swift's built-in
support for both.
So in Swift 4.2, all of these
types will conform to Codable so
that you can very easily do
things such as encode and decode
JSON for all of these different
types.
[ Applause ]
Of course, debug printing in
Swift is actually even easier
than in Objective-C because you
don't have to do any additional
conversion.
The built-in introspection of
the types can allow you to print
them directly.
So in Swift 4.2, you just
actually pass these types
directly to your print functions
if you want to print them out
for debug purposes or log them.
And then finally, you may
already have some existing code
that was using the behavior of
the old string conversion
functions and need a compatible
functionality going forward.
And so for that we've actually
just renamed all of these and
moved them to be properties on
NSCoder.
This really helps to emphasize
the fact that the intent of
these methods was to be used for
encoding and decoding, so it's a
pretty natural fit for them to
go over there.
So these are just a few of the
consistency improvements that
you'll find across the iOS 12
SDK for Swift 4.2 but you'll
find many more as well.
Now speaking of encoding and
decoding, NS Secure Coding, in
iOS 12 there are now new secure
by default encoding and decoding
APIs.
Adopting NS Secure Coding for
all of your encoding needs on NS
Keyed Archiver is really key to
ensuring that you're protecting
your customers from both
malicious and corrupted data.
You'll also find that the older
insecure APIs are not
deprecated.
So you can learn all about that
and get much more detail on it
in the Data You Can Trust
Session on Thursday at 9:00 a.m.
And that's framework updates.
Next, let's turn our attention
to some enhancements to a number
of existing APIs and we'll start
with notifications.
Notifications has a number of
really great improvements in iOS
12 but we're going to focus on
just three this morning.
Interaction within custom
notifications, grouping of
notifications, and access to
your notification settings
within your own apps.
So let's start with interaction.
Now custom notifications have
for a while now allowed you to
define a predefined set of
actions for those notifications.
In iOS 12, this set of actions
is now no longer static.
It can be defined
programmatically and you can
change them at runtime.
In addition to these actions,
and even better than that, the
notifications themselves can now
be made interactive.
So for example, here, you can
see Messages is now allowing you
to reply quickly to a message
inline directly in that
notification.
Now in addition to interaction,
iOS 12 now includes grouping of
notifications by default and the
default behavior will be to
group all the notifications for
a particular app into a single
group.
But, of course, your app may
have custom needs to have more
granular groupings so something
like iMessage will group all of
the messages from a particular
conversation together and
separate from all the rest of
the notifications for that app.
Now you can adopt this in your
app as well by just tagging your
notifications with a particular
thread identifier and then all
the notifications for that
threat identifier will appear in
a single group.
Now the UI updates for
notifications in iOS 12 also
include some new ability for
users to customize the delivery
behavior of their notifications.
But, of course, your apps may
also include some existing, more
granular controls for
notification management within
your apps as well.
And iOS 12 introduces a new API
that makes it easy for your
customers to get directly deep
linked into your notification
settings UI exactly when they're
looking for those more granular
controls.
So you can learn more about all
of these notification things in
What's New in User Notifications
and Using Grouped Notifications
later this week.
That's notifications.
Next, let's talk about messages.
Now messages in iOS 12 includes
some really new and exciting
features in the camera.
And you can bring all of your
iMessage stickers directly into
the camera as well.
If you're using the Xcode
sticker template, this will work
automatically by default with no
additional work on your behalf.
But if you're building a more
custom sticker experience using
the MS Messages App View
Controller, some small amount of
adoption is required.
Now there's a new MS Messages
Supported Presentation Contexts
API that you can add into your
user info plist and then specify
that you want to appear both in
the messages context and the
media context.
Once you've done that, your apps
will appear both in the App
Strip and also within the
camera.
Now if at runtime you need to
figure out which context you're
in so that for example you want
to customize the display of your
stickers a little bit, there's a
new API for that as well.
By checking the presentation
context, you can quickly see
whether you're in messages or in
the camera.
Now in addition to these
features, iOS 12 also brings a
new access for interaction to
your messages apps.
In compact mode, previously
swiping horizontally down in
your messages app would switch
between apps.
In iOS 12, these horizontal
swipes and interactions that
move horizontally are now
available for us by your apps
directly so they'll interact
with your apps rather than
switching to a different app.
And that's Messages.
Next, let's talk about automatic
passwords and security code
autofill.
Now iOS 11 introduced automatic
passwords or password entry into
your apps.
And in iOS 12, we're taking
these a whole step further.
But let's go back to the
beginning for a minute and talk
about the entire experience.
So for users that have passwords
stored in iCloud Keychain, since
iOS 11 it's now been possible to
have those automatically get
populated into your app in your
login flows.
Now in iOS 12, these passwords
can also be stored into iCloud
Keychain from your apps both
from your login window flows and
also from your password change
request UIs.
As soon as a user logs in,
they'll be prompted to save the
password to iCloud Keychain.
Now even better, iOS 12 can
automatically generate passwords
in your new account flows and in
your password change flows.
Adopting this is really easy.
You just make sure that you've
tagged your password fields with
either the password text content
type, if it's a login field, or
the new password text content
type if it's either a new
account or password change
field.
If your services have a specific
requirement on passwords for
example if they got required or
disallowed characters or if they
have other requirements such as
maximum number of consecutive
repeated characters, you can
specify these requirements as
well to make sure that the
automatically generated
passwords are fully compatible
with all of your requirements.
Now, the final bit of friction
during some of your login
experiences is when you have to
take that two-factor
authentication code, get it out
of a text message and into your
apps.
IOS 12 makes this really easy by
automatically identifying these
notifications, noting the
security code in them, and
suggesting it right in the Quick
Type candidate bar so that it's
really easy to get it right into
your app.
Now the only thing you have to
do to make sure this works in
your app is to be sure that
you're using standard iOS text
interaction APIs in order to
accept these passcodes.
With all of these new features,
iOS 12 is enabling a much more
secure future with unique,
strong passwords used for every
service that you never have to
memorize or type ever again.
You can learn all about this in
the Automatic Strong Passwords
and Security Code Autofill
Session later this week.
Now, our final API enhancement
topic is actually a bit of a
review but now with a little bit
more context.
So in iOS 11, we introduced Safe
Area insets.
Safe Area insets are a really
great way to make sure that your
content is avoiding any overlap
from other parts of the user
interface such as bars on the
top and bottom of the screen.
This is really great on iPhones
where bars are pretty
straightforward, but it's really
powerful as well.
Safe Area insets give you that
safe area coordinate in the
local coordinate space of any
view in your application, so it
scales even the much more
complex interfaces, things like
iPad Split View which has
different height bars on the
master and detail side of the
Split View.
The Safe Area insets in any view
underneath these bars will be
appropriate for the amount that
they're overlapped by the bar on
their side of the split.
So this is really great on
devices with rectangular screens
but it also is really powerful
on devices that have
non-rectangular screens like
iPhone X.
Now, you can see here we've got
our larger bars at the top and
bottom than we have on devices
that have home buttons.
And the Safe Area insets
obviously have just grown to
accommodate that larger size.
Now, unique to iPhone X is that
there are Safe Area insets even
in cases where no bars are
present and this extends the
landscape mode too where it can
really help you make sure that
you've got a rectangular area at
all times that's safe to display
content and will never be
clipped.
So I want to thank you all for
those of you who have adopted
Safe Area insets and updated
your apps for iPhone X.
It's been a really great
experience over the last year
and I'm sure most of you have
already done that.
If you haven't, now is a really
great time to do so.
Your customers will always
prefer apps that are being kept
up to date and support for
iPhone X is a really visible
indicator of that being the
case.
So if you haven't, definitely go
do it now.
And to help make sure you have
all the information necessary to
do that, you can check out the
UIKit Apps for Every Size and
Shape Session later this week
which will tell you both all
about Safe Area insets and all
of the other related inset APIs
all throughout UIKit making it
easy to make sure you have apps
that scale to every shape and
size.
So that's our framework updates
and our API enhancements.
Next, let's talk about Siri
Shortcuts.
So Siri Shortcuts is an exciting
new API in iOS 12.
Siri Shortcuts makes it easy to
get common actions out of your
app and make them accessible via
Siri.
Now, Siri Shortcuts can be
suggested proactively right on
the coversheet making it easy to
access actions that you would
want to access at the exact time
and place that you want to
access them.
Even better, they can also be
suggested right on the Siri
watch face on Apple Watch.
Now not only are Siri actions
suggested proactively but they
can also be set up to be
executed using a custom voice
phrase.
Now, adding Siri Action Support
to your apps is really easy.
You can use two APIs.
There's NS User Activity, which
you may already be using for
support for Handoff and
Spotlight integration, and
there's also support for Siri
Intents for more complex
scenarios where you have more
custom interactions.
So let's look first at NS User
Activity.
Now as I mentioned, NS User
Activity is a common API with
Handoff and Spotlight and this
could be a really great API to
use if your Siri Shortcuts
should get your customers back
to a specific place in your app,
for example loading a particular
message or document, the same as
you would do if you were trying
to hand that off to another
device.
If you're already doing this,
it's really easy to add support
for Siri Shortcuts.
You just set Eligible for
Prediction to true.
And if you're not, this may
still be a great way if your
shortcut fits into one of these
categories.
Now, if your app has other more
custom needs or if you just want
a lot more control, you can
adopt the Siri Kit Intents API.
Now Siri Kit Intents provides a
number of predefined intents
that you can easily adopt on
your own.
These are the same as the Siri
Kit Intents in previous years.
Now if your apps have more
custom behaviors, though, you
can now in iOS 12 define your
own custom intents.
Custom intents can be really
flexible and they do anything
that you would want.
In this case here, I've created
one to help me create my WWDC
slides next year.
Now the categories that you
could put your intents in to are
pretty broad already.
So here I've used the Create
category.
But if your intents are even
more generic than that, there
are even more general ones
available such as General Do,
Run, and Go options.
Now once you've created your
intent, you also want to make it
really easy for your customers
to create these custom shortcuts
to get to them.
And so there's now an API from
right within your app you can
allow customers to create a
custom voice shortcut.
So here I've got a button that
will just bring up a new panel
enabling me to create a new
shortcut right within my app as
soon as I finished an operation.
So if you're doing something
like ordering a coffee in the
morning and you notice it's
something that might be done
again, this is a great
opportunity to offer to create a
Siri Shortcut to do that next
time.
Now even better, you can also
combine these shortcuts together
using the new Shortcuts app
available from the app store.
So you can learn all about this
and much more in the
Introduction to Siri Shortcuts,
Building for Voice Siri
Shortcuts, and Siri Shortcuts on
the Siri Watch Face Sessions
later this week.
So we've talked a lot this
morning about what's new in iOS
12, but there are also a number
of great sessions that are worth
mentioning that aren't
necessarily about what's new.
So if you're new to creating
apps for iOS, there's a really
great session you should check
out called I have This Idea For
an App.
So definitely check that out.
And if you already have an app,
and are just looking to add more
polish, there's a couple other
great sessions as well, A Tour
of UI Collection View and Adding
Delight to Your IOS App.
So thanks so much for coming out
this morning to hear what's new.
Look forward to seeing you in
the labs and I hope you have a
great week.
Thanks.
[ Applause ]