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

Configure player

Close

WWDC Index does not host video files

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

URL pattern

preview

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

$id
ID of session: wwdc2018-235
$eventId
ID of event: wwdc2018
$eventContentId
ID of session without event part: 235
$eventShortId
Shortened ID of event: wwdc18
$year
Year of session: 2018
$extension
Extension of original filename: mp4
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2018] [Session 235] UIKit - App...

WWDC18 • Session 235

UIKit: Apps for Every Size and Shape

Frameworks • iOS • 40:17

Ground-up coverage of how to make an app that can fit on devices of every size and shape. Make your app fit beautifully on Apple's full range of devices with the minimum amount of effort, future-proofing your user experience along the way.

Speakers: David Duncan, Tyler Fox, Russell Ladd

Unlisted on Apple Developer site

Transcript

This transcript has potential transcription errors. We are working on an improved version.

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 ]