 My name is Jin Han, and I was a developer here at SDS. So today, my title is actually called Updating Adaptive Apps, but actually, this is a very general title. And the adaptivities in iOS actually mean many things. So I may be referring to that you're building an app that's taking care of the specific color gamemodes for different screens. Or maybe it's referring to your building app for some sort of hardware features that's only available on some of the devices. But today, we're not going to talk about any of them. Today, we'll only put our focus on adaptive layout. So this is going to be our agenda. So this presentation is going to be separated into three sections, namely the safe area, layout margins, and US review. And perhaps after these three sections, we won't have enough time to talk about some more stuff. So I put them in the list. So if you are interested, then you can go online and you can do that Google yourself. And in order for you to view a clear mental model on a presentation, I'm going to structure this presentation for each of the three sections into this flow. So first, I will give you an API checklist. And then I will give you a brief intro that's specific to this section. And then I'll show you a demo, which is the main part. I'm going to show you what to take away of today's. And then in the end, I will complete the entire section with a calculation of that. So now let's start with the safe area. The API strategies for safe areas are actually like this. There are a total of five APIs, three on the UI view and two on the UI view controller. So speaking of safe area, actually, this is a relatively new concept that's initiated by Apple two years ago since the launch of iPhone X. And for all the devices with rectangular screens, actually, the safe area spans across the entire screen. And I mean the hardware safe area right now. And for iPhone X series, iPhone X, iPhone XS, iPhone XS Max, actually you have this extra space on the top and bottom that's taken away from this safe area. And that one is actually reserved for the sensor housing on top, as you can see. And also the bottom is reserved for the home indicator. So if you put the iPhone X in the landscape mode, then you have this metric layout on the left and right, which is again reserved for the hardware. And now this time you have the bottom area taken out and that one is for the home indicator. So for iPhone X updates, for iPad it's similar. You have the top and bottom is taken away. But actually there is one more case for the Apple devices that the safe area only reside within a particular area of the screen and not of the edge of the safe area actually reach the screen itself. So that case is actually Apple TV. So there is a concept in the television manufacturing industry, which is called over scan composition. The basic idea is that only part of the input pictures is rendered on the screen. So some of the input signals is ignored. And Apple modeled this for the TV OS as a safe area. So if you are developing a TV OS app, actually you can just confit on a free of staff inside a safe area. And those staff will be actually visible on the TV. And now we see how the safe area is appeared on the devices, but actually as developers who are more concerned with how can we access those features and those properties. So actually Apple provided us two APIs. Both of them are on the UI view. The first one is called a safe area inset. And this one is actually a UI edge inset. It's very straightforward. You have a top, have a bottom, and have a left and right values that represent the length of that on safe region. And then you have this safe area layout guide, which is a UI layout guide that you can use all those nice features of UI layout guide like the many layout anchors or layout frames if you want. So this is about how the safe area appears in each UI view instance. So next we're going to talk about how this, how the safe area of behaviors will change when you have the entire view hierarchy. We'll have an entire set of views. So I will have our first demo right now. So the focus of this demo actually, the first one I will show you is the subview propagation. And the next one is when you want to add in some extra assets or some extra insets to your UI view, then how can you do that? And what is possibly the case that when you want to add in this inset? So we'll switch to our app. So this is the demo app that I'm going to use today. So basically it's separated into two different sections. And for each section we're going to show one more property of the presentation. And before we actually dive into any of it, I'd like to show you the project first. So first of all I make this demo project mostly using storyboard because it's very fast for prototyping but if you want to make it using code it's completely fine. The API set is exactly the same and you don't have to worry about it. So we're going to go into this subview propagation. Just to clarify, actually in this view now we have two subviews. The first one is the gray colored view which spans across the entire screen. And the second one is the white one in the middle. Actually I have a subclass for this view which basically does nothing except it draws out the current safe area layout guide, the layout frame of the layout guide. So right now we can see the yellow box is actually the safe area layout. The safe area of the outer view and the pink, I don't know whether you can see it on this screen, but there is a pink rectangle over here. That one is actually the safe area of the white square. So right now we can see the safe area for the small view is actually span across the entire view. This is because this subview now is completely reside within the safe area of the super view. So that means everywhere inside the subview is safe so everywhere is safe area. So now let's try to move this view a little bit out of the safe area of its current view. So right now you see there's a pink line actually at the bottom. So now we can see the safe area has already updated for the subview and it is actually the intersection between the subview and the safe area of super view. So this section is actually straightforward because basically it means that anywhere unsafe that for parents probably means it's unsafe for you too. But this statement is not always true. So let's try to move this view even further. So I see actually there is a limit for the safe area to update. If you move beyond this limit, actually the view will stop updating its super view. Maybe for the guys in the back, we can show you on the top, the behavior is the same. So if you are carefully enough then we can see that this limit actually is the safe area inside of its current view. So that means the largest safe area inside of the subview is actually the safe area inside of the current view. And the reason for this actually is for the sake of the animation. So imagine this view is actually a panel that is sliding up from the bottom and you want to do this animation nicely. So if this view, if this behavior doesn't exist there then probably your animation will start from a line which has a zero height and everything will be squeezed together. So that is not the behavior that we want. So I guess this behavior is generally works for everybody here. And then we go to the next one which is the additional safe area inside. So for this view controller I'm actually adding a safe area inside on all of the edges on the top, bottom left and right. So if you want to do this as well it's actually very easy. There is a property on the UI view controller. So this class is a subclass of the UI view controller and there's a property called additional safe area inside. You can see it, right? But that's important. Okay. So what you need to do is actually just to assign any UI edge inside to this property. And the view, the safe area inside and safe area, a little guide of the view will be automatically adjusted. Perhaps right now you might be wondering what is the case that I really want to make use of this property? So what is the case that, first of all, what is the case that Apple uses this property? Actually for all the first party classes like UI navigation controller, UI type bar controller we're using this property right now in, I think it's from iOS 11 and onwards. If you have noticed that actually we have those navigation bars and when those navigation bars is translucent actually our content of the child view controller can go beneath the bars. And actually Apple is doing this, is doing this kind of behavior, is adjusting all those insides, safe areas using this property. And one of the case that I can think of that way as developers might want to make use of this property is about the keyboard handling. So I guess for most of the app, if not all, when I want to take care of the keyboard handling because perhaps for most of the app we have to accept some certain kind of testing input. So if you want to do this, then actually the work is not really trivial. You need to observe to those keyboard animations. You need to extract what is the height of the keyboard, what is the animation time, what is the curve and you need to do the animation. Maybe even worse, you may need to do a secondary layout just specifically for the view that the keyboard is visible. But actually if you want to do this for every screen then it becomes really a mess. Whenever you have some kind of logic adjustment you need to do it everywhere. So my solution for that, for this demo app is actually we have this view controller as a subclass of view view controller. It is the parameter and it is the root. It has a child view controller in this case I call it content view controller. So this controller, the job is simply observed for the keyboard events. Namely these are keyboard will change frame, will show and will hide. And it will extract out the parameters from the notification. And it will assign the correct value to the additional set of inside of interview controller. And then lastly we will do an animation. So what is the result of this? Maybe we can show you that. I actually provided two examples over here. The first one is of the scroll view. So we can see, actually this view it doesn't even have a customized view controller. I just created this view using the storyboard. So basically it has a scroll view. We can see the secondary inside is already incorporated into the content inside here. And we have a USX view. So when I tap this we have the keyboard. And we see the content inside is already automatically adjusted when the keyboard is visible. So for the other case, this USX view in the middle. You can see it right now. So there is a USX view in the middle. And it's actually aligned with the center Y anchor of the safe area layout guide. So when the keyboard is visible the position of this view is automatically adjusted according to the latest safe area layout frame. So actually all of these behaviors are come for free when you actually write in your travel controllers. What you need to do is just to lay out your stuff according to the safe area layout type. But actually there is some drawbacks of this of course because this API is only available from iOS 11. So if you're supporting some kind of device that's before this then perhaps you'll still need to stick to the old way. And there's another drawback is right now I can show you my storyboard. This keyboard container view controller instance is actually the initial view controller of my entire app. So sometimes this can create some kind of problems that maybe your app is really complex and you have certain screens that it doesn't want this behavior. But it's relatively easy to overcome. You can just provide maybe a customized probably on your view controller or you can just grab this view controller just outside of the controller that you will directly need it. So I think that one is fine. And that's about the additional safe area I want to talk about. So we can return to the slides. Let's do a short recap. So what is the propagation behavior of safe area? The safe area of the sub view is actually in what word is the intersection between the sub view and the safe area of the parent view. But in some cases, the safe area will not be updated. It's because the maximum safe area inside of the sub view will be the safe area inside of parent view. And in the case that you want to add in some additional safe area inside to your child view, actually the driveway to do is to associate a view controller with it. And you set this probably called additional safe area inside of your view controller. Then all of your sub views and the safe area insets, the safe area layout guide will be adjusted automatically for you. So now let's come back to see this API list again. We've covered the safe area inside, the safe area layout guide, and in the UI view controller, we've covered additional safe area insets. For the two callback methods we haven't mentioned yet, but we'll talk about them together later with the callback method of the layout margins. So let's talk about layout margins. Again, for the API at least, there is a six API on the UI view is related to layout margins. Four of them we might be already very familiar with, layout margins, layout margin guides, directional layout margins, and layout margins, they change. And we'll have maybe these two are less familiar with. There are the insets layout margins from safe area, preserved, super view layout margins. We'll talk about these two later in the demo. And for the UI view controller, we have this callback method, which is similar to the layout margin to change in the UI view. We have view layout margins to change, and we have two methods that's related to the system minimum layout margins, which we will talk about in the demo as well. So what about layout margins? The diagram looks very similar to the safe area. So again, we have a UI layout guide, which is called the layout margins guide. And again, you can use the layout frames and all the layout entries. But the difference between the layout margins and the safe area, actually, for the insets part, now we have two properties. The first one is the layout margins, and we also have a directional layout margins. So what's the difference? Layout margins is a UI edge inset. It has a property of top, bottom, left, and right. But in comparison, directional layout margins is an NS directional edge inset. So instead of left and right, now it has the leading and trigger. So perhaps when you are dealing with some language that reads from right to left, then maybe the one that you want will be the directional layout margins. But this API, again, is available only from iOS 11. So if you are supporting all the devices, you have two ways. The first one is your calculus, and you'll find out what is leading and trigger yourself. The second way is that you just use the layout margin guide. And that one's supposed to be leading and trigger. So our second demo. In this demo, I will show you four things. The first one is what is the system minimum layout margin? And the second one is the intersection, the interaction between layout margins and safe area. And then we'll talk about the propagation behavior of margins, what's the difference, and what's the similarities. And then lastly, we'll talk about callback behaviors for the layout margin to change and safe area to change. So let's return to our demo app. The next section. So when I get into this section, actually you can see two rectangles here. The first one is the yellow one, which represents the safe area of the entire view. And the blue one is actually the layout margins of the entire view. So perhaps you have already noticed there is a left and right padding on this view, and that is actually the system minimum layout margins. This margins is provided by the system, and I think as developers we shouldn't do any overrated on this problem. This problem is, by the way, under the UI View Controller. So if you do not really want this property to affect your layout, there is an option, a property on the UI View Controller as well called a view respect system minimum layout margins. So if you turn this off, then we can see the blue box actually tends to fill the yellow box completely. So we're gonna try it again. So this is about the system minimum layout margins. And what about the interaction between layout margins and safe area? So in this case, in order to make it clear, I added additional safe area inside for this view controller. 100 points on top and bottom, and 32 points on the left and right. So where it is, right now the safe area margin, the layout margin is calculated from the safe area. So if you don't want this behavior, this behavior is actually by default because sometimes we're doing layout margins, we don't want to put our stuff outside of the safe area. So Apple decides to make it as a default behavior. But if you do not want this, there is a property on the UI View called inside layout margins from safe area. So if you turn this off, then we can see actually the layout margins will span, will be calculated based on the bounds of the view instead of safe areas. So we try it again. So again, we have a left and right padding and that's the system minimum layout margin. So what's about the propagation for the layout margins? In this view, we have firstly the white background view, that's the larger view, the pattern view. And then we have a sub view which has a yellow background and the blue box, if you can see, the color is a bit messed up, but okay. But yeah, but there is a blue box, you can see the add will appear, right? So this blue box is referring to the layout margin of the SuperView. And there is a white background box and that one is the layout margin of the child view. So by default, the layout margins between, the layout margins of the SuperView and child view doesn't affect each other. Because the layout margins is actually a relatively independent stuff for each of you and generally we do not want them to affect each other. But if you, in your case, you really have a need to make it propagate to the sub view, then you have this option under the UI view called Preserves SuperView Layout Margins. So if you turn this on, then we can see the layout margin layout, the layout margin guide layout frame is actually will shrink to suit for the layout margins of your parent view. By far, I think these three properties are relatively easy and straightforward to understand. So let's talk about some callback behaviors. So for the callback, actually we don't really need to look at a screen because the screen is empty and I prepared some little quizzes for you guys. So I gave you some context first. This view controller is very simple, nothing is inside. And this is a child view controller which is going to be pushed to a navigation stack. So I have four quiz questions for you. Basically there are just four functions and I have some very simple statement inside. And I'm going to either call them here in view develop or here in view develop here. So maybe we'll try this first. If I type quiz zero here in the view develop and we'll print A in the safe area inside the change callback and we'll print B in the layout margin in the change callback. So can you guys think of what is going to be a final output after everything is done? Can I have some response? Definitely A. Definitely A. Only A. Only A. No, actually we can see it. Let's try to run this. And the result, as we can see, actually BAB, it's very strange, right? But actually if we put a break point here if we can see the stack trace then it will become more and more straightforward. So let's do it one by one. We got a first B. And we have a very long, sorry, we have a very long stack trace over here but I just want to want you to notice one of them. It's actually this line. Oh, shit. Okay, now I'll read out for you. Let's get back to the original. And this line reads, UIView underscore update safe area inside. And this happens because we are pushing this view controller into a navigation stack. And navigation controller as I mentioned just now actually provides some additional safe area inside. And plus we're using an iPhone 10 so the device itself already have some hardware safe area inside. So, remember whenever you update your safe area inside your mail margins is actually calculated based on the latest value of this safe area inside. And for some reasons, if we see the next callback is the safe area inside the chain, right? It's actually firing from the same methods. Again, the update safe area inside. So for some reason, I have decided to call the layout margin update first before the safe area inside the chain. So, I think it's just a factor we need to remember but the whole process is actually initiating from this safe area inside update by the SuperView controller. And then we have the next one, the next speed. The next speed you will have a even longer trace. And I think the important method of this is called this. It's a UI ViewController Update Content Overlay ESat with a rat in bonds of Ancestor ViewController via immediate trial of Ancestor. Maybe this method sounds very confusing but actually what it does is actually adjusting your system minimum layout margins. So remember we have a system minimum layout margin and by default we didn't set any of the layout margins for this controller. So there is a minimum one that applies to it and this is the time that the system is doing this adjustment. So that's why there is a second B for this. So I think we are clear about the quiz zero because we haven't do anything yet. Quiz zero is empty. So what about we try the next quiz? Quiz one. Quiz one, we still call this in a beauty load but right now we are assigning the directional layout margins to have a value of leading 20 and treating 20. So what about the output right now? Let's try to run this again. It's BBA. And maybe you're quite surprised but actually it's still fine. We can't understand what the BA is right. It's still calling from the safe area but what about the first B? And where is our last B? So the first B is actually calling directly from here. So again if we turn on this grid point we're gonna try it again. We can see in the statuaries, actually this is calling from our own methods. It's the quiz real controller does quiz one. So whenever you update this property it will trigger or call back immediately. And then since this has a leading of 20 and treating of 20. But our system minimum layout margin is actually a leading of 16 and treating of 16 in the case of UI real controller. So after you're doing this and after the system adjusts it's a very inside and then they found actually all your layout margins is already larger than the system minimum layout margins. So there is no more updates triggered so the last B is not happening. And then we have this quiz two. Quiz two in contrast with quiz one actually I changed from 20 to five. And actually the result of this and I'm not going to run it again. You can see the answer over here. It's actually BBAB. The last B appears because this layout margin now is smaller than the system minimum layout margin. So the system minimum layout margin updates the layout margin of this view again. So we have another call back. And for the quiz three it's about the safe area inside. And in this case, since this property is a UI real controller and we're assigning them inside the view deep load. And at this time the safe area inside is not updated by SuperViewController yet. So it doesn't matter. This line actually doesn't affect any of the output. So in this line, quiz three will be the same as quiz eight which will have a BAB. So I wanted to skip the part for view did appear because after the view did appear basically the system has already adjusted the safe area inside. So basically for the answers all will start with a BAB. And what's next actually depending on what have you changed. If you change the safe area inside, then it's a BAB. If you only change the layout margins and it's greater than the system minimum layout margins then it's only a BAB. If you are setting a layout margin that's smaller than the system minimum layout margin then it's going to be nothing. So I hope you are clear with this and we're going to return to our slides. Let's have a recap. So about the system minimum layout margin. And this is a property under the UI ViewController. And if you do not want this you can simply leave this probably if you respect system minimum layout margin to false then your view will completely be laid out. Your layout margins will completely be calculated based on the value that you provide. And by default the layout margins is calculated based on your safe area inside. And if you do not want this behavior then you have to leave this inside layout margin from safe area to false. Then your layout margins will be calculated from your bounce. And by default there is no propagation for layout margins. But if you want, there is a property under the UI View that preserves super view layout margins. You can make it to true and your layout margin will start to propagate. And again, the view controller is being shown. Actually the first method, the first relevant method in this case is called ViewView will appear as something happens and view d move to window callback will be called. And after that, the UI key will update the safe area inside to that view. And after that, the UI navigation controller will handle its own system minimum layout margin. And this explains why the behavior is like that as we're showing in the demo. And then in the end, in the very last end the controller.View did appear for show final. And when the safe area inside is shown, if you didn't turn off the option that you tell UI key do not calculate your layout margins based on the safe area inside, actually the layout margin callbacks are always called before the safe area callbacks. And the view callbacks are always called before the controller's callbacks. So let's return back to this API for this again. We have covered the layout margins, the omargy guides, the original layout margins, the margin will change. And we'll also cover these two relatively use less often, the less often used methods. And we'll also cover the system minimum layout margins in UI view controller. And also the callback, the view layout margins will change. And then we have our scroll view. So the API for scroll view is also quite easy. There is one, automatically adjust scroll view insets on the UI view controller. And we have six on the UI view, or UI scroll view. The bonds, common size, common inset, common offset, and common inset are actually quite commonly used for user everyday. And there is one more newly added API called just a common inset, which is added in iOS 11. And finally we'll have this common inset adjustment and that will be our focus for this section. So let's first talk about some fundamentals. So you can think of a UI scroll view as a picture frame. And the bonds of the scroll view is actually the frame itself. And the content of the scroll view is the actual picture content of your picture frame. So right now we have a bond size of 400 points height. If we have a content height, which is larger than the frame height, then we can scroll this content. So in this case, we have a content size of 500. And right now the top edge of the content is aligned with the top edge of the frame. So right now we have a content offset of zero. And now if we scroll to the bottom, then we see the content offset is updated from zero to 100. And if we're going back, the content offset is reset. And we have this new concept called common inset. And this probably actually only referring to some extra area that you can scroll your scroll view to. So right now it's zero because this is the limit that we can scroll our scroll view. If we update to 40, that means we have some extra space on top that we can scroll our scroll view into. And then if we scroll to the bottom, basically nothing changed because we haven't adjust the content inset of bottom. But if we scroll back, now the offset can be netted 40. So this idea of common inset becomes very important. I think since I was seven because we have all those translucent bars and generally want to put our content to beneath those bars and we have those nice and beautiful blurs. This is the reason why Apple provided this API. It's automatically adjusts scroll view of insets on the UI view controller. It's there to help us to help us to adjust all the content insets of the US scroll view. So you don't have to calculate all those bar hide yourself. The UST will do it for you. But there is a one big problem of this because when the UI key tried to do this adjustment, it's actually updating the value of the content inset of the scroll view. If you have some very complex, complicated view logic that maybe you have a header on top of the scroll view that you want to set the content inset yourself, the UI key update will overwrite your change and that will cause some issues. It's either you update happens before the UI key updates then your update is lost or your update is after UI key is updated and UI key update is lost. So your content will have to overlap with something. So that's all good. So Apple decides to duplicate this API and instead provide another API called adjusted content inset. And this one is actually very straightforward it's on the US Proview. And adjusted content inset is actually just the net value after you sum the content inset and the system inset. The content inset now is fully controlled by the developers. So the system will not try to update any value of this content inset anymore. And the system inset will basically means all those setter insets for example. And another thing to take note of is that this one, this probably is a get only property. It's really only. So you cannot do any like ugly stuff with it. And let's get back to this diagram again. So right now we have a kind of inset of zero on top and a save error inset on top of zero. So the adjusted kind of inset will be zero. So again the top edge of this view of the content is actually aligned with the top edge of the scope view. And if we're adding some save error inset the content inset is not changed because that's controlled by the developers. But the adjusted content inset is changed. And in response, the UI view will update its layout according to this updated adjusted content inset. So now let's try to remove this content inset and try to add a subview. So you just now will have mentioned that the UI view will by default propagate the save error inset to its subviews. So when I try to screw my screw views up, part of my subviews will actually goes beyond the save error of the super view. So what happened right now? Maybe now you're thinking of, okay, so my subview will start receiving some save error update events and maybe my layout will be updated as well. Actually that's not the case because in this case the screw view has already incorporated the save error inset into its adjusted content inset. So it will stop propagating the save error inset into its subview. Because if you think about it actually, when you incorporate the save error inset into your adjusted content inset, you're already handling this inset once. So if you are propagating this to your subview again, it's like a double counting for the same value. So that's not logical. So to help us like manage and control this kind of propagation behavior and adjusted content inset adjustment behavior, we have this new property called content inset adjustment behavior. Actually it is an enumeration. Under the UI screw view it has four cases, all this rollable access automatically and never. And we're going to show them one by one in the demo. So in this demo first of all we'll have a look through of all the options and then we'll show you some of the paid falls of the options. So let's get back to you here. So here we have this content inset adjustment behavior section. So the first of all is about all this. All this right now seems actually completely fine. So we have the top inset adjusted so we don't have any overlap content under the navigation bar and the bottom save area is also adjusted. And we can see that actually the screw view will go beneath the bar and have the blur effect. But actually this is not the issue. But the issue happens when you try to, when you try to have your phone in the landscape mode. So right now you immediately will see there is a white region on the left. And if you try to touch it, you can see this screw view right now is actually horizontally screwable. The reason for this is actually we're setting the content inset adjustment behavior to automatic. And that means it's going to incorporate the save area from all directions. If it's in landscape mode, that means on the left hand side we have the hardware save area inset. So it's going to make your screwable area larger. And it's larger than the bounds of your screw view. So that makes this screw view to be horizontally screwable. So imagine this screw view is a UI table view then your table will become horizontally screwable and that is very weird. So we don't want this behavior in general. And then we have the next behavior called screwable axis. Screwable axis actually is there mean to solve the issue that happens just now. So right now the screw view will only adjust its content inset on the axis that is screwable. So right now if you put this phone in horizontal mode, I will see that this one is no longer horizontally screwable because the UI screw view doesn't incorporate the save area inset on the left and right into its adjusted content inset because in this axis the screw view is not screwable. So it seems fine, but this is only for the long content. If your content is short, for example this case, then let's see what's happened. It's actually part of the content that is overlapped with the navigation bar and you cannot screw this anymore because the content is shorter than the frame height of the UI screw view. So the UI key will think, okay this screw view is not screwable. So it will stop and cooperate those save area inset into the adjusted content inset and that will result in this overlap. There are two ways to resolve this. The first one is you set this property it's called always bounce vertical to true and to tell UI key explicitly that this axis is screwable. But this one have some side effects that means if your content size is shorter than the frame height then your screw view can always bounce vertically. Sometimes we may want this behavior but sometimes we may not. So in the case that you really don't want this behavior then we have the next option called automatic. So automatic basically behaves the same way as screwable axis but the difference is now for even for the content size which is shorter than the frame height of the UI screw view you will still have this adjustment for this axis. And again if you are in a landscape it will behave the same way as the screw axis. So basically this one, this automatic will be the one that we will mostly use. But however there is another issue with this. So if you still remember this API maybe the phone is too small on the screen but it's the automatic adjust the screw view inside under the UI view controller. If you still have this API if you have some kind of lexical and previously you decided to set this API before then you adjust your content inside yourself. And now if you set this content adjustment behavior to automatic then it will disable all the next features that we have talked about just now. So right now it will just behaves the same way exactly the same way as the screw axis. So right now you cannot scroll and the content is overlapped under the navigation bar but for longer content actually it's still fine. And in the end we'll have the only last case which is never. So never is also very straightforward. That means the UI screw will not cooperate any of the same error you set into this adjusted content inside. But this one have some side effects. That means the UI screw will start to propagate the same area to its sub-views. So basically the idea is whenever the screw view doesn't incorporate a safe area into its adjusted content inside then it will propagate a safe area to its sub-view. So right now I'm actually this top label is a sub-view of the first blue box and I'm layouting the label against the safe area layout guide and the top edge. So right now if we try to scroll this we see the relative position of the top label actually changes inside its sub-view. Sometimes we may make use of this behavior to create some very interesting effects but sometimes actually most of the times we do not want this behavior. So the same thing will happen at the bottom as well. So if you drag through this we see the relative position of this label actually changes in its sub-view. So that's about the never case of this content inside adjustment case. And let's have a short recap of this demo. So for the case always some issues is if you have some kind of unexpected system inside and this will result in some extra adjusted content inside of your screw and this will give you a larger scrollable area and in the end you will have an extra access to scroll in some ways. And then we have the scrollable access but the problem of this one is that if you have an insufficient content size that means the access is not scrollable to your keys. And that means there will be no adjustment applied to that, maybe it's top and bottom, maybe it's the left and right to those safe area inside. And this may result in some unexpected effect. And for the automatic, generally this is the one that we're going to use but we need to be careful with the deprecated API that automatically adjusts scroll view in sets. So I will suggest that we do a version check on this. So if you are still on some older on some older versions you can maybe you can turn this thing off and you do the adjustment yourself but on the later like iOS 11, iOS 12 perhaps you should use this automatic one. And then in the end you'll have this never and never means no adjustment. No adjustment means the safe area from all directions will be propagated to the subways and sometimes that means when you scroll some of the layout of your subview will change. So let's get back to this API showing something. We have talked about the deprecated automatic adjusted but automatically adjusts scroll view in that, in sets and we have talked through all the properties listed here for the US scroll view. And this is the combination. For UIV we have talked about my UIV controller right top of six, and UIV scroll view six. And what's next about that, that we are, I think we are already a bit over time. So if you're interested there are still some really common layout guide available in the UIV controller and in your I2O will scroll and you have some safe area with the APIs in your I2O table view. And you have this sizing classes which is there are many for you to create completely different layout for iPhones or iPads or landscape and portrait mode. And you have this dynamic type of font. So you can download the slides and demo in these URLs and these are the two references I use when I prepare this talk. Actually, this video, this is a video from the WWDC last year actually covers most of our topic today. If you still have something that's unclear and you're interested, please go ahead to watch this video, it's very nice. And again, what's important, that's a hurry. So if you're interested, please go to this URL or you can visit our HMS, I think it's all there, they are playing your phones. Okay, and thanks very much.