WWDC2018 Session 235

Transcript

[ Music ]
>> My name is David Duncan.
I'll be joined on stage by my
colleague Tyler Fox and Russell
Ladd.
And we're here to talk to you
about building apps for every
size and shape.
So I don't know how many of you
were here back when we released
iOS2 on the original iPhone.
But you had one screen size to
work with then.
But today, we've got iPhones.
We've got iPads.
Multiple sizes.
We've got the iPhone 10, the
brilliant new screen, and a new
shape for you to build your apps
to.
For this talk we're going to be
using our Bagel Times app as an
example of a design that adapts
beautifully to iPhone 10 and
iPhone 8.
And so these are the three
things we're going to be talking
to you about today.
I'll be speaking about safe area
and layout margins.
How you can use them in your
application to adapt to various
screen sizes and shapes.
Then Tyler will come up and talk
to you about scroll views.
How they interact with safe
area, layout margins, and other
UIKit technologies.
And finally, Russell will get up
and talk to you about using all
UIKit tools to build adaptive
applications.
And so with that, let's get to
talking about safe area and
layout margins.
So what is a safe area, and what
does it look like on the devices
that you've come to know and
love?
Well, on an iPhone 8 with a
rectangular screen, the entire
screen is a safe area.
All of it's there, no overlaps
on your content.
On iPhone 10, there's a little
extra space that's taken up on
the top and bottom by the
hardware that will be taken away
from the safe area for your
application.
And in landscape, you've got
something kind of similar where
we've given you a symmetric
layout with space on the bottom
for the home indicator for you
to lay your content in safely.
But what other devices might
have a safe area that's not the
entire screen?
Well, Apple TV actually might
give you the situation because
certain TVs will have a screen
that actually extends past
what's visible to the user.
And those will represent their
information based on something
called overscan compensation.
And that overscan will be
represented as a safe area in
any apps that you build for
Apple TV.
So now that we've seen a few
examples of what the safe area
looks like at the screen of a
device, how does that get to
your views?
And how do you use that in your
own applications to build
adaptive applications?
So let's just pick up an
arbitrary view.
Whole thing.
There are four insets on the
top, bottom, and left and right
that represent areas that might
have some kind of overlay or
other thing that might occlude
your content if you placed it
there.
You can access this on your UI
views using the safe area insets
property.
A UI edge inset that has those
four values.
Now if you're doing layout with
Auto Layout, you actually might
want to just see the entire rec
that's safe.
And you can get that by looking
at the safe area layout guide.
Which is a UI layout guide that
represents that information.
It has layout anchors for you to
do Auto Layout with.
And a layout frame if you just
want to see the actual
rectangle.
So now that we've seen how
that's represented on our view,
let's take a look at how it gets
from one view to the next.
So we'll just take away the text
and add a subview.
And this is going to cover most
of the bottom edge of that view.
Now, how does the safe area get
calculated for this?
Well, as we saw, that subview
that we just added, it intrudes
on the unsafe parts of the view
on the left, right, and bottom
of its superview.
And so those are the values that
you will see in the UI edge
insets represented by the safe
area insets property on that
subview.
And similarly, you'll see a safe
area layout guide whose layout
frame looks kind of like this.
Now once you've seen this, and
you've got a view, you might
want to actually add additional
insets for your UI.
You might decide that you want
to add controls through your
view controllers that will then
add to the safe area or subtract
from the safe area for your
subviews.
So we'll go ahead and add
another subview here.
And along with that, it will
have a view controller because a
view controller is where we
actually have the property that
allows you to add additional
insets.
And that property is called
additional safe area insets.
We're going to go ahead and
inherit the insets we got from
our parent.
Add those additional safe area
insets to this view.
And finally construct the final
safe area that let-- , layout
guide.
What other things might you want
to know about how safe area
behaves in your application?
Well, let's take a look at
another example.
Here we've got one view safely
inside of the safe area of its
parent.
So that view safe area, of
course, encapsulates the entire
region of that view.
And we'll move it closer to one
edge and as you might expect,
we're not going to gain a safe
area because we haven't left the
safe area of our parent yet.
We'll move a little bit further
out, and you'll see that the
bottom inset on that safe area
now grows a little bit.
It takes up a part where it
overlaps, where it extends
outside of the safe area of its
parent.
And as we move closer to the
edge there, it continues to
extend.
Now what might you expect to
happen if we move this view
further off the bottom edge of
its parent?
Well, how about that?
The safe area did not grow any
further as the view moved
outside of its parent.
No matter how far outside of the
parent that view might go.
And you might be asking
yourself, "Why would that, why
would we do that?
What's the purpose here?"
And the answer is animation.
In this particular case, we're
moving this subview out of its
parent.
We wouldn't want the content to
stay inside of the safe area
because then it wouldn't move
with its own parent.
And as an example, we can see
this app.
Where we're going to pull up a
view on the bottom.
If that view had been laid out
against the safe area of the
parent, or its parent, and that
parent's safe area would extend
the farther it grew off the
bottom of the screen, then this
area would have stayed on screen
during the entire transition,
which would have meant that you
would have not seen the
background come up with it.
And so that's why the safe area
never grows larger on any
dimension than what its parent
provides.
So to summarize that safe area
part, let's took a look at how
you can interact with it.
Again, we've already mentioned
the safe area insets property
and the safe area layout guide
property.
But if your view needs to react
to when safe area insets change,
then you can override the safe
area insets did change method.
Typical thing you might do is
just call set needs layout.
But if there's any additional
logic you need to run, that's
okay too.
If your view controller needs to
respond to its view safe area
layout changing, then you can
override view safe area insets
did change on your view
controller.
And finally, if you're doing
your interface in IB, you can
use that safe area property
that's shown in the view list to
build your constraints against
the safe area.
And so a safe area is explained.
Let's talk a little bit about
layout margins.
So layout margins are padding.
They're a property that, in
general, you have full control
over and allows you to specify a
space from the edges of the
view.
Just like with safe areas,
they're represented by a UI edge
insets property, this time
called layout margins.
Now last year, we also added
directional layout margins.
These differ from layout margins
in that layout margins use a UI
Edge Insets value while
directional layout margins uses
an NS directional edge insets.
And the primary difference
between those two structures is
that directional insets use
leading and trailing instead of
left and right, which makes it
really easy for you to create
layout margins that adapt to RTL
layouts.
So you don't have to do the
swapping between left and right
when you use directional layout
margins.
Now, just as with safe area, we
provide a margins guide as well
called a layout margins guide
that you can use with Auto
Layout to layout content against
that margin.
And then we go ahead and put our
content inside of that view.
Now the next question you might
be asking since we're talking
about layout margins and safe
areas together is how do the two
interact?
Well let's go ahead and bring
those markers back.
Oh yeah, I meant to talk about
how you can change those
[inaudible] layout.
So with safe area, by default,
we build the safe area, and then
we build the layout margins with
respect to the safe area.
And we do this for the perfectly
obvious answer that by default,
you probably actually want this.
You want your layout margins
inside of the safe area because
they represent additional
padding against the layout that
you want to do.
But we thought to ourselves,
"Hey, some people may not
actually want this."
And so we made it very easy for
you to flip this default.
And so if you just change the
insets layout margins from safe
area property from true to
false, then we'll go ahead and
move layout margins back to the
bounds of the view.
As a [inaudible] instead of
being encapsulated inside.
So what else can you do with
layout margins?
Well, we already saw that by
default, safe area margins
propagate down the hierarchy.
But with layout margins, they go
by default.
Because by default, your layout
probably wants to be fairly
independent with margins as
opposed to safe area, which
represents a concept that really
is for the entire view
hierarchy.
But if you want to have
propagation, you can flip this
on view by view by changing
preserve super view layout
margins from false to true.
And we'll go ahead and line up
those margins that are smaller
than the parents in order to
make sure that everything lines
up naturally between a child and
its parent view.
Now in years past, you've
probably also tried to change
layout margins of your view
controller views.
And if you look at what we do by
default.
That this margin that you'll see
against that view.
Now we additionally added a
property last year called system
minimum layout margins and these
margins are the minimum margins
that we've combined against any
margins you provide now to
create the final margin.
So if you wanted to add to the
top and bottom of this, you can
do that without disturbing the
left and right margins that
UIKit provides.
But again, you might want a
little bit more control.
And so there's another property
called view respects system
minimum layout margins.
If you want your margins to be
completely underneath your
control, flip this to false, and
we'll use your margins as you
describe them, no questions
asked.
And so to wrap up with layout
margins, the properties you have
on UI View are the layout
margins property, edge insets,
left, right, top, bottom.
Directional layout margins.
Great for your RTL layouts.
Top, bottom, leading, and
trailing.
The Layout Margins Guide that
you can use with Auto Layout to
do all this there.
And finally, if you have logic
for when the layout margins
change in your view, you can
override layout margins did
change and do whatever logic you
need to do there.
In Interface Builder to create a
constraint that ties against the
margin, just check that
constraints to margins box.
And so with that, I'll bring up
Tyler Fox to talk to you about
scroll views.
[ Applause ]
>> Thanks, David.
Good afternoon.
And as David mentioned I'd like
to talk a little bit about
scroll views today.
So scroll views are a really key
part of the iOS experience.
And they show up all across the
system.
You have them in table views,
collection views, UI text view,
and of course in all of the
custom application in all of
your apps.
And so in our app, Bagel Times
that we've been working really
hard on as you can tell, this is
our news article screen.
And everything as you can see is
sort of centered around a scroll
view with the article.
And this is we want to you know
really showcase the high-quality
content our writers are putting
together.
Like, you know, exploring the
true inspiration for, you know,
Apple Park.
And we want to review some of
the basics about how you can use
scroll views in your apps to
understand how they can help you
adapt your content to devices of
different shapes and sizes.
So to do that, we're going to
walk through an example here,
and we'll start with a
full-screen scroll view.
And on the left I'm going to
show you what things look like
on more or less a real device.
And on the right, we're going to
look at kind of things behind
the scenes.
Understanding what's happening
in a diagram.
So everything that we talk about
today is going to apply in--
we're going to talk about the y
axis of everything vertically.
But everything also applies
equally to the x axis.
And we're also going to use some
simple values for illustration.
So in this case we'll say that
our scroll view has a height of
400 points.
Now inside of your scroll view,
you'll have some content.
And you can think of the scroll
view a lot like a metaphorical
picture frame.
The scroll view size represents
kind of the fixed frame of the
picture frame.
And then inside of that, the
picture is your content.
And the content can kind of
slide around as if it's on ball
bearings.
Now in this case, our content is
vertically scrollable.
And that happens because our
content has a taller height via
the content size than the scroll
view's height.
And here I've turned off
clipping on this diagram on the
right so we can kind of peek
behind the scenes at what's
going on.
So scroll views use content
offset as a way to represent the
current scroll position of the
scroll view.
Right now, we're scrolled to the
very top.
So our content offset is at
zero, meaning our top edge of
the content is aligned with the
top edge of the scroll view.
Now, if we go ahead and scroll
the scroll view down, that will
slide our content up.
So let's scroll to the bottom
and watch that happens here.
And as you can see, the content
offset increases and goes all
the way to 100 in our example
when we reach the bottom.
That's because the top edge of
the sc-- the scroll view is now
100 points below the top edge of
that content area.
If we set a content offset of
zero on the scroll view, that
will put us all the way back up
to the top.
And we're back where we started.
So that's pretty much just the
basics of scrolling a simple
scroll view around.
Now let's talk about a very
important concept about
extending the scrollable area of
the scroll view.
And we do that through a
property called content inset.
So content inset is a mechanism
for you to provide insets that
you can specify from the edges
of the scrollable area of the
scroll view to the content
inside.
So adding content inset
increases the scrollable area
and makes the scroll view able
to scroll to a larger area.
So let's set a content inset on
the top edge here and see what
happens.
So here we've set a content
inset of 20.
And as you can see, that extends
that top edge of the scroll view
so that the scrollable area is
now larger.
Now when our content offset is
sitting at zero, our content is
still aligned with the top of
the scroll view.
But the scroll view could
actually scroll even farther
towards the top now.
So let's scroll around like we
did before and watch how things
have changed.
We'll scroll to the bottom and
just like before, we're still
here at a content offset of 100.
That's because we didn't change
anything on the bottom edge.
And we still have a bottom
content inset of zero.
But if we now go ahead and
scroll back all the way to the
very top, we end up with a
content offset that actually
goes negative.
That's because we are now able
to scroll beyond the top edge of
our content.
And so we can scroll as far as
the negative content inset on
the top edge.
Now starting in iOS 7, this
content inset technique became
really important and that's
because with iOS 7, translucent
bars became really common across
the system.
And the idea was that you would
display your content edge to
edge.
And it would underlap the bars
so that you could get these nice
colorful blurs with your content
through the bars, right?
Tool bars, navigation bars, and
so forth.
So because this was so common,
we wanted a way to help
automatically set the content
inset on your scroll views to
make this easier in your apps.
And to do this, we had a
property on UI View Controller.
And this was called
automatically adjust scroll view
insets.
And the intent, intent again was
to automatically set the content
inset on your scroll view
whenever it had overlapping bars
coming from a navigation bar or
a tool bar.
And that was whenever your
scroll view was inside of a view
controller.
Which itself was contained
inside of a navigation
controller.
Now this worked pretty well for
some common cases.
But if your app had a more
custom or advanced usage of UI
scroll view, sometimes having
your code setting content inset
and also UIKit setting that same
content inset property could
create some challenges.
And so starting in iOS 11, we
have a much more explicit and
powerful way for you to get the
same automatic behavior.
And the mechanism for doing this
is a new property on UI scroll
view which we'll talk about now
called adjusted content inset.
So starting in iOS 11, we
introduced a new property on UI
scroll view.
It's read only.
It's adjust content inset.
And this basically describes how
the scroll view is actually
going to behave.
Well you're probably asking
what's the difference between
this adjusted content inset and
the content inset that we just
talked about?
Great question.
Here's how it breaks down.
Adjusted content inset is equal
to the content inset that your
app provides plus any automatic
insets coming from the system or
UIKit.
And so because we now separate
these two, it's a lot easier to
reason about what's happening.
Of course you might be wondering
where and when would I get a
system inset on my scroll view.
Well, one most common case will
be safe area insets.
Let's look at how this works.
So we're back to our basic
diagram here.
But we're going to bring some
safe area insets into the mix.
So if we go ahead and start out
right now we have no safe area
insets on any edge.
But we'll go ahead and add some
safe area insets to the top edge
of our scroll view.
And what you'll see is that by
default, the scroll view is
automatically absorbing those
safe area insets on its top edge
into its adjusted content
insets.
And that's because our scroll
view's vertically scrollable.
And so what this does is this
automatically increases the
scrollable area and makes it so
content can scroll out from
underneath anything covering up
the top edge like a bar or even
the edge of the display.
So take a look at an example
here where we have the same
scroll view on two different
devices.
iPhone 10 on the left, iPhone 8
on the right.
And you can see this is a real
example, the top safe area inset
is larger on the iPhone 10
because of the larger status bar
height and the sensor housing.
And as a result, the scroll view
has a larger top inset-- that's
the gray region that's shaded at
the top here.
So this is one way that scroll
view helps automatically adapt
to any device that it's running
on.
Now let's go back to our diagram
and talk about something else.
When we have a scroll view like
this where we have top safe area
insets, let's go ahead and add a
subview to our scroll view.
And we'll put this right in the
content area.
And so right now this-- this
subview is sitting fully inside
of the safe area in the scroll
view.
But what if we start to scroll
the scroll view down which will
move that content up?
Just like this so that part of
that subview is now sitting
outside of the scroll view safe
area?
Based on the safe area inset
propagation that David just
talked to you about, you might
be thinking, okay, that means
the subview is going to start
seeing its own top edge safe
area inset.
That's actually not what
happens.
The reason why is because when a
scroll view absorbs safe area
insets into its adjusted content
inset, it will no longer
propagate those same insets down
to its subviews on that same
edge.
This is really important.
Scroll views use scrolling to
move content around and move it
out into the safe area.
And if a scroll view were to
also propagate safe area insets
that it was using to extend its
scrollable area, it would almost
be like double accounting for
those same insets in two
different places.
And so as a result, the subviews
on the scrollable axis are kind
of completely unaware that there
are safe area insets on the
edges that the scroll view is
absorbing them into its adjusted
content inset.
So now that we understand how
scroll views work together with
safe areas, let's cover the
options that we've exposed to
let you control this behavior.
The mechanism that you have to
do this is a property on UI
scroll view called content inset
adjusted behavior.
And it also is available on
interface builder as you can see
here.
Now the default value for this
is automatic.
And most of the time, if not all
the time, you're really going to
want to leave this at its
default value.
But we want to walk through the
options so that you understand
what they do and know that
they're available.
And so you can make the right
choice in your apps.
So we'll start with the first
one.
The first one is the always
behavior.
This is pretty straightforward
as you might expect.
Scroll view is going to always
incorporate any system inset
like safe area insets into its
adjusted content inset on any
edge.
And this works fine in our
particular example here.
We only have a top and bottom
safe area inset on our scroll
view.
And so it will incorporate those
and the content gets to move out
from underneath the bars.
We don't have any horizontal
insets on the left or right.
So no problems.
But be careful with this one
because if you have something
like let's say a table view on
the iPhone 10 in landscape,
there are left and right safe
area insets.
Using this behavior the table
view is going to incorporate
those into its adjusted content
inset, which increases the
scrollable area, which is going
to make a table view
horizontally scrollable.
You're not going to want that
behavior.
That's why we have the next
behavior which is scrollable
axes.
For this one, the scroll view is
going to independently consider
things on the vertical axis and
the horizontal axis.
For each of those, if the
content size exceeds the width
or the height as appropriate, or
if you set the always bounce
horizontal or always bounce
vertical properties to true,
then the scroll view considers
that axis scrollable.
And it will go ahead and
incorporate in the system inset
into its adjusted content inset.
So in this example right behind
me we have a long article that's
scrollable.
And so we're getting those
automatic insets incorporated.
But what if we had a shorter
article?
Let's take a look.
Okay.
Here's a shorter article.
What's going on here?
Let's take a look under the nav
bar and see what's going on.
Ah.
Looks like we've lost our system
inset because it's not
scrollable anymore.
So our title's stuck all the way
up underneath the status bar.
So let's put back the nav bar
and talk about how we fix this.
Well, one way could be you could
set always bounce vertical on
this scroll view if that's the
behavior you want.
That will make the scroll view
always vertically scrollable.
Or we'll get to our next
behavior, which is automatic.
And so automatic works basically
the same as scrollable axes,
which we just talked about.
But it has one additional
behavior as part of it that is
when the scroll view is inside
of a navigation controller, the
scroll view will go ahead and
adjust its top and bottom
content inset even if it's not
vertically scrollable to account
for top and bottom bars.
So, even in this case where we
have a very short article, it
still means that we're getting
the right insets.
And this is generally the
behavior you're going to want.
And that's why we have it as the
default.
Just one quick heads up though.
If you are setting the
deprecated automatically adjust
scroll view inset property to
false, that will disable this
behavior.
And so it's going to behave
basically like scrollable axes.
Alright, that brings us to our
last behavior.
Never.
Now with this one, as you
expect, that means the scroll
view is never going to adjust
its content inset.
However, that has some side
effects.
For one, that means that the
scroll view will end up
propagating safe area insets on
all of its edges just like a
regular view.
And as we talked about before,
that might end up giving you
some behavior you don't really
want.
For example, if you recall your
layout margins are relative to
the safe area, which means your
layout margins might end up
increasing or changing as a
result of this.
This is also going to disable
some very helpful automatic
behaviors that scroll view
provides like automatic scroll
indicator insets.
And so if you do a search online
and you see a favorite, you
know, question and answer
website suggesting that you set
your scroll view's content inset
adjustment behavior to never,
consider instead using
additional safe area insets to
increase the safe area insets.
If your goal is to try to
express to the system that
you've added let's say a toolbar
or some sort of other overlay.
Or you could consider just
modifying the content inset
directly, the property that we
talked about in the very
beginning.
That's for you to control.
And you can use that to add or
subtract from the effective
adjusted content inset that the
scroll view will see.
So with that, I'd like to hand
it over to Russell to tell you
all about how to put this
altogether.
[ Applause ]
>> Thanks, Tyler.
Now we've introduced many
adaptive APIs to help your apps
over the years adapt to
different environments.
And safe area is really just the
newest of these.
So I'm going to review some of
these concepts and also talk
about how they work with safe
area.
So let's go to the first screen
of our application.
And we've got a pretty standard
setup here with a tab bar
controller, continuing
navigation controller,
containing our content view
controller.
Now note that the views of all
three of these view controllers
are full screen.
This is what enables the tab bar
to extend underneath the home
indicator, the navigation bar to
extend underneath the status
bar, and the content to extend
and scroll underneath all of it.
But we need to prevent these
elements from overlapping.
So let's see how safe area
allows these components to do
that.
So the safe area insets start by
flowing through the tab bar
controller, which only receives
insets on the home indicator and
status bar because that's all
that it sees.
Since the navigation controller
is inside of that, it also
receives a safe area inside in
the bottom that accounts for the
tab bar.
And the content view controller
inside of both received safe
area insets that account for
both bars.
Now what does the story look
like in landscape?
Similar.
There are safe area insets in
the top and bottom.
But there are also insets on the
left and right that account for
the size of the screen.
And those are propagated all the
way down from the screen through
the view controller hierarchy.
Now I want to stop here and use
this example to make a point
about how you should think about
using safe area when you
implement your own views.
So this custom view shouldn't
know that it's running on an
iPhone 10.
It shouldn't even know that it's
contained inside of container
view controllers.
This is the idea of
encapsulation.
If your views only read the safe
area insets that are provided to
them on all four sides, and are
able to adapt to different, to
arbitrary safe area insets, that
will ensure that your views will
be able to, will be modular, can
be moved throughout your
application and run in
different, different
environments and still not be
occluded.
Now let's jump to an article and
talk about hiding the status
bar.
So hiding the status bar is a
technique that would reclaim 20
points of vertical screen real
estate on rectangular screen
phones.
And we're just doing this by
overriding preferred status bar
hidden in our content view
controller and we're turning
true.
And this preference is then
propagating up through our
contained view controller
hierarchy and respected by the
root-- the root of the system.
Now unfortunately on iPhone 10,
preferring the status bar hidden
does not also hide the sensor
housing.
So we can't slide content
underneath it.
[Laughs] So UIKit will protect
you and will not allow you to
create this UI.
Instead, the behavior of
navigation controller on iPhone
10 is that it will always
display the status bar when the
navigation bar is visible.
So if you want to hide the
status bar and reclaim vertical
real estate, our recommendation
is to hide the navigation bar
and status bar together.
And, in general, when you want
to go-- when you want to create
an immersive experience, go
immersive and just hide all of
your overlays and controls
together.
Not only does this look good and
help your users focus on their
content, it's also a design
technique that will adapt well
to all of our devices.
Now, speaking of immersive
experiences.
Let's switch to the iPad and
talk about rendering text in a
very wide environment.
So here you can see we have
text, and it's not extending all
the way to the edges of our
view.
The problem with doing that, if
we had rendered the text all the
way to the edge, is that it can
become difficult to read, for
your eye to track from one line
of text to the next at a given
font size.
And so the solution is to always
render text inside of a readable
width, a recommended readable
width provided by the system
based on the user's currently
selected dynamic type font size.
Dynamic type being another
adaptive element of our iOS.
Now you can get the readable
width with this API on UIView
called the readable content
guide.
So this is another layout guide
just like the layout guide for
margins and safe area.
And it works just the same.
And I mentioned that this
readable width depends on the
user's currently selected
dynamic type size, which means
if the user changes their
dynamic type size in Control
Center or the setting app, the
readable width will get smaller
or larger to compensate.
Now let's switch to portrait and
bring in our sidebar with our
article list to make the context
for our article display much
narrower.
So here the maximum recommended
readable-- readable width is
much wider than the space we
have to display the article.
And the thing to note is that
the readable content guide will
still not report the maximum
readable width necessarily.
It'll be clamped to the layout
margins, which means you can be
confident in laying out your
views against the readable
content guide.
And not worry that they're going
to spill outside your margins.
Now let's see how this works on
a context for a safe area
exists.
The readable content guide
functions just like-- just like
layout margins where its insets
add to those provided by the
safe area insets.
Now normally at the regular--
the default dynamic type font
size of the system, the readable
width is going to be wider than
the width of a device of an
iPhone in any orientation which
means it won't come into play.
However, even iPhones, if the
user selects a smaller dynamic
type font size than the default,
it can come into play, so it's
still nice for your application
to adopt.
Now let's jump back out to our
article list table view and see
how readable width can work
here.
Now the thing to know about
table views is that they use
their layout margins, I'm
talking about the margins, to
layout a lot of their UI
elements.
So that means the separators,
the system accessories as well
as the labels in the system cell
styles.
And any views you lay out inside
of your own custom table view
cells, if you laid them out
against the margins, will play
along as well.
So that means if you adjust the
margins of a table view, you can
move all of these elements
together.
So if you have a table view with
a lot of multiline text in it,
it makes sense that you would
want to adjust the margins of
the table view to bring all
these elements into alignment
and still respect the readable
width.
So to do this, table view
provides an API.
Called cell layout margins
follow readable width.
Now when it's false, table view
will use its normal system
margins.
And if it's true, all the
content will inset.
Now, something to note is that
the default value of this
property has changed in iOS 12.
It is now false by default.
It was previously true.
This shouldn't affect the
behavior of your appl-- of your
applications too much,
especially on phones.
Our general recommendation is to
leave the default alone and set
it to true when you know that
you have a table view that's
going to contain a lot of
multiline text where it would
make sense.
And this property's also
adjustable from Interface
Builder with the follow readable
width checkbox.
Now keeping with table views but
moving on from readable width,
there is something else to know
how they work with safe area,
which is that the content views
of your table view cells will
not extend beyond the safe area.
However, by default, the
background and selected
background views do-- of UI
table view cell do extend beyond
the safe area.
So if you have some content you
want to place in custom table
view cells that you want to
overflow outside the safe area
and bleed to the edges of the
screen, you can either place it
in the background or selected
background views if the
semantics of those views make
sense.
Or there's a property on UI
table view called insets content
views to safe area, which by
default is true, but you can
change to false to get your
content views to also extend to
the edges.
And this property is also
configurable from Interface
Builder.
Now let's rotate back to
portrait.
And in the main screen of our
application, we mentioned this
sheet that slides up from the
bottom before containing a
picker view.
Now the safe area of the screen
here means that we have to
adjust the layout of the picker
view to be inside this safe
area.
And most of the system controls,
like UI picker view and other
controls, and probably controls
of your own many views don't
make sense to have to know
anything about the safe area.
Because it's not clear how they
would respond or like re-lay out
themselves internally.
So we have a recommended
technique for handling the
layout of these kinds of views,
which is to place them inside of
the container view.
And the responsibility of this
container view is simply to
position its safe area unaware
content inside the safe area by
analyzing the safe area insets.
And it can also provide the
background, which extends beyond
the safe area and makes your
control feel connected to the
edge of the screen in this case.
The-- another technique we want
to talk about related to safe
area and positioning elements
close to the edge of the screen
is when you have a control or
button that on one device you
may want to place directly
against the safe area and on
another device where the safe
area insets are zero you may
want some padding.
And the reason for doing this in
design is that the safe area
insets can sometimes incorporate
some implicit padding.
So let me bring-- I want to
provide you a single solution
that will work for both of these
situations.
So let's bring in a diagram, and
I'm going to give you two auto
layout constraints that will
produce this result in these two
different situations.
So the first constraint we need
represents the padding that we
would other-- we would normally
add.
So this is just a constant
constraint from the bottom of
the super view to the bottom of
our control.
But in this case, we're going to
make it not required so that we
can break it when the safe, when
the safe area insets are
non-zero.
The second constraint is an
inequality constraint from the
bottom of our control to the
bottom of the safe area.
This ensures that our control is
always inside the safe area.
So if I change the safe area
insets to make them non-zero,
you can see that the inequality
constraint ensures our content
is not clipped while still
maintaining some minimum
padding.
Now we've talked about many
different adaptive APIs in this
talk and in previous talks.
Layout margins help keep lots of
your elements aligned.
Safe area insets protect your
views from being clipped or
occluded.
Readable width keeps columns of
text comfortable to--
comfortable to read.
Size classes inform when you
should make large structur--
structural changes to your
applications.
And these APIs we use to
implement higher-level
components in our frameworks.
So scroll views, tab view--
table views, container view
controllers.
The other kinds of things we
talked about today reuse these
things to ensure that our
high-level components can adapt
to all of our devices in the
simplest way possible.
So the takeaway is for you to
design your applications in
terms of these adaptive
primitives as well.
The advantage is that-- instead
of coding for a specific device.
Your code will be simple,
flexible, and it'll guarantee
that your applications are as
future-proof as possible for all
of our different environments.
For more information, these
slides and recording will be
available online.
Thank you all for coming, and I
really hope you've enjoyed the
conference.
[ Applause ]