Safe areas on iPhone X wrong - ios

I have a pretty complex app, that causes the safe areas on an iPhone X to be wrong (pushed down).
This screenshot is from a storyboard. It's a container view aligned to the bottom anchor of the Safe Area Layout Guide.
Everything looks fine there and produces the correct result in an empty, new project.
But as soon as I instantiate and push the view controller in the original app, the result is this:
What could cause the safe areas to be distorted?
The property additionalSafeAreaInsets is definitely not set anywhere in the app. I've played around with a couple of other UIViewController properties, but nothing seems to change this.
Thanks!

Please share constraint layout view for your button to get proper/exact solution to your problem.
Here I had same problem.
I had added another view as a subview (gray view) in a main view and moved my button in it. I enabled the safe area layout guide for both main view and gray view.
Safe area layout for gray view safes my button inside safe area.
iPhone X, Layout Preview:
Hope this may help you!

Click on the View(which contains your button) and then check Safe Area Layout Guide

So to perfectly answer my original question:
What could cause the safe areas to be distorted?
Turns out a totally different part of the app was modifying the size of the parent view controller's view.

Related

iPhone X - safe area layout guides - I want my app display on full screen, not only in the safe area

I have a problem with my code. My application displays within iOS safe area layout guide, however I'd like to force it to display "outside". I have searched the internet and unfortunately I found only "reverse" problems. I don't use interface builder, all my views I create programmatically. I have a main view controller which starts up automatically with the app and from here I start creating all my stuff. My interface builder just shows this view controller and a view assigned to it. Interestingly, the view appears to be really full screen when viewed in IB.
Yes, I tried turning on/off the "Use Safe Area Layout Guide" option for the view. Also I tried to use topLayoutGuide and bottomLayout guide instead and constrain the main view to them, but it still fails:
- (void)viewDidLoad {
[super viewDidLoad];
UILayoutGuide *margins = self.view.safeAreaLayoutGuide;
[NSLayoutConstraint activateConstraints:#[[self.view.topAnchor constraintEqualToAnchor:self.topLayoutGuide.topAnchor],
[self.view.bottomAnchor constraintEqualToAnchor:self.bottomLayoutGuide.bottomAnchor]
]];
//...
}
This is what I see in the IB:
1) view
2) safe area - I can't get rid of it in any way:
3) result (simulator / real device):
I also did RTFM but a) I'm stupid, b) I'm too tired, c) both
Any help would be appreciated :)
If you use constraints on the view, it will usually automatically align to the safe area. You can override this and have it constrain to the superview instead by clicking the little arrow to the right for a drop down menu:
You then select "View" instead of "Safe Area". Also make sure to un-click "Constrain to margins" or it still won't fill out the whole screen.
I resolved my issue. The application was not displaying in full screen because of missing launch image in my assets for iPhone XR. Because of this iOS was falling back to the closest launch image keeping aspect ratio, thus defining the application size.
The second issue (not loading the image, displaying some default splash screen insead) - removing the app from device and installing from scratch helped.
Thanks everyone involved :)

UINavigationController offset from top of screen like phone app does when on a call

I am looking for an elegant reliable way to drop a UINavigationControllers frame down by 20px in order to create a tappable area, much like the native phone app creates when on a call...
I have tried things like manually setting the UINavigationContollersviewframe in viewWillLayoutSubviews() but this feels like the wrong thing to do and I would need to write a whole bunch of clauses to layout correctly for iPhone X style screens and rotated devices.
Is there any auto layout I can use to do this elegantly? Any guidance much appreciated.
Make the root view controller a custom parent view controller that determines the tappable area on top, and everything else becomes a child view controller whose view frame is now up to you.

Is it possible to set constraints for root view in XIB?

Recently i was following a tutorial to create frameworks in Swift, Where they create reusable visual effect view just like we see in Xcode build success pop up. I was doing the UI step by step where they created a new xib file and dragged and dropped UIVisualEffectView into it.
In the above image we can see that the UIVisualEffectView doesn't contain any constraints. It only has auto resizing masks in size inspector(as expected).
But the following image from the tutorial suddenly contains all necessary constraints for it's root view.
I'm already aware that we CANNOT, by default set any constraints for the root view. But in the tutorial the author seems to have added constraints for the same. I'm just curious to know if it is possible to do that or am i missing any fundamental idea ?
EDIT:
Constraints for root view.
OK, found one way to do this...
Haven't done any testing, so I'm not sure if the constraints are really set correctly or will be used by auto-layout at run-time, but this will put them there.
Create a new "View" XIB - this is how it looks to start:
Add a Visual Effect view to this view, and give it width and height constraints of 230 / 230:
Now, drag that Visual Effects view *out of the plain view, onto an empty space:
You will see it maintains its constraints. Then delete the original view, and add the other elements:
As you can actually see on your screenshot the width/height constraints belong to the View (first subview of Visual Effect View).
Look at the green line:
I don't know what's going on your tutorial (and I have no intention of watching it), and I have no idea under what circumstances the screen shot was achieved. But I do know the rules for how a view controller's main view gets sized.
Any view controller's main view must expect to be resized as it is placed into the interface. The size in the storyboard is therefore meaningless. That is why you cannot give it a size with auto layout.
If a view in a xib or storyboard is to be used as the main view of a view controller, it is meaningless (and would be wrong) to set constraints on it, because it will be the task of the view controller's parent (or, in the case of the window's rootViewController, of the window) to set the size of the view when it places it into the hierarchy.
If a view controller wants to vote on the size of its view when it is placed into the view hierarchy (for example, as a popover), that is what the content size (preferred explicit size) is for. But even then, the parent is the one who controls what actually happens.

Interface builder position off screen

I have a container view showing a sidebar which is pinned to the main views leading edge. The sidebar is initial visible which is fine for iPads however I would like it to be hide initially for smaller devices. To do that I need to set the side bars trailing edge constraint to be (0 - its own width)
As far as I can see this is not possible in the interface builder. I have tried to do it in the viewDidLoad, checking if the device is an iPhone before doing self.sidebarX.constant = -self.sidebar.frame.width. This fails because viewDidLoad has not set up the views yet so the width is wrong. I also tried to do it in viewDidLayoutSubviews however the user sees the sidebar disappearing which isn't nice. I am sure there must be a common way of dealing with this?
I finally worked it out. viewDidLayoutSubviews was the correct place to be doing this. At first when I tried it, it was showing the sidebar slide away as the view controller loaded. It turns out this is because I was calling my closeSidebar method which animates the side bar moving off screen. Changing this so it just sets the view off screen and adding a check to ensure this only done once on first load (as viewDidLayoutSubviews is called multiple times) does the job of hiding the the sidebar for certain devices without anyone seeing it happen.
You can set this using xcode adaptative layout:
You can set the different position for all different screen types here, changing the constraints, positions, sizes to each different type you need.
You can install the layout of one object in different screen types using the dialog below:
Have a look in this 2 parts tutorial from raywenderlich part 1 part 2

Extra space on top and bottom of Init View Controller

I have a swift app I have been working on for some time now. I noticed that my init view controller has extra space at the top and the bottom of the view, so much that it allows me to pull up and down on the first view and let go and have it spring back into where it was. I removed all my constraints thinking I had an issue with them, but it's still done the same thing. The size class is set to any any, and all my graphic fit inside the view, yet I still an able to pull up and down.
I also made sure my view, wasn't a scroll view, it's not.
I looked around for similar issues, but couldn't find anything like this.
Thanks for the help!
Here is what my view looks like in IB
When I run the app.
Showing the amount I am able to pull it down from the top.
If you remove all of your constraints, and the storyboard is set to use auto layout, it usually won't show up correctly, as you have seen. You will have to add the constraints to each element in your view controller. To do that, you can control click on each and drag it where you want to connect a constraint. Or, use the pin and align buttons in the bottom right corner of the storyboard view.
There is a good tutorial from apple that I suggest you read. It will help you with the basics of using auto layout. Another option would be to not use auto layout. To turn it off in the Storyboard, go to the file inspector and uncheck the box "Use Auto Layout".

Resources