Auto-layout constraints not working as expected - ios

I've got a UITableViewCell that has a child view, and within it an image view and a label. I am wanting to use the child view as a means of giving some margin around the contents of the cell, thus giving me margins inbetween cells. This seemed to be the way a lot of people online recommended doing it.
I've set up my constraints as shown below:
I have performed a Update Frames on all views in the view controller. The story board shows it exactly as I'm expecting it to be on the phone. When I run it on the phone though, I get this...
I'm completely baffled at this point. I've spent two days of reading and trying to layout a simple UITableViewCell and clearly don't have a good understanding of how auto-layout works still.
I've even just laid everything out along the suggested boundaries (the blue lines) and then told the storyboard to generate suggested constraints. At which point the content of the cell just sent with 50% of it off the right side of the screen and un-viewable.
So two questions:
The storyboard more often than not shows me something that is not accurately represented on my actual device. Is this fairly common in iOS development? Should I not be relying at all on the storyboard auto-layout representation?
What do I have to do to these constraints in order to get the cells to layout on my device, like it is shown in my storyboard at this time? What constraints am I setting wrong?

Storyboard doesn't display the content according to any device by default. You can set it to your current device in its size properties(by default it is "Inferred"). Constraints are used to display the views equal on all devices. They automatically adjust UIelements according to display size. So if you want your app to run on devices of different sizes you have to rely on constraints.
I think you are setting too many constraints. Happens if you are new to auto layout. Try reading this guide. Its very helpful.

Related

UITableViewCell margin inconsistency (Static cells)

I have an interesting issue with a margin inconsistency between different devices. Here are 2 screenshots from iPhone X and iPhone 6+ respectively with the same iOS (11.4.1) and running the same app.
You can see that on the iPhone X everything is aligned properly (as well as in IB), but on the iPhone 6+ there's a 4 pixel inconsistency.
This is a table view with static cells. All the menu items are the Basic style, except the second one ("Offline mode") which is in Custom style with custom constraints. In basic style the UILabels have X=16. My custom constraint also has a constant value of 16.
Of course, I can change my custom constraint to 20, but then the situation flips. So on the iPhone 6+ it will be all aligned properly, but will be misaligned on the iPhone X.
I tried to find out where these 4 pixels are coming from, but found nothing. Please help.
The problem is that you have pinned your label's leading edge to the edge of the content view with a constant of 16. That is not how the other cells work, so you get different results.
Instead, pin your label's leading edge to the left margin of the content view, with a constant of 0. The left margin is 16 on a smaller device and 20 on a larger device, which is exactly the difference you're seeing for the other cells (because that is exactly how they are configured).
Matt's answer is correct. I just want to add more details, because it may be beneficial for someone else. So, it turns out that all I need to do is to check the following checkbox in my constraint properties in IB:
Looks pretty simple when you know where to look for.
Generally as soon as you start needing to control the margins etc of table view cells your best bet is to leave the built-in stuff behind and make custom UITableViewCell subclasses with explicit constraints and subviews.
In this particular case the screen width is different and the basic cell type calculates its margin constraints relative to the screen width. If you look on the right side you will see the same kind of inconsistency with the positioning of your switch control relative to the disclosure indicator in other cells.
(EDIT: Easiest solution, depending on what you're aiming for, is as matt suggests, pin to the margin of the content view rather and the actual edge.)
If you want, you could adjust your own constraint on your custom cell so that it is not constant but relative. You could figure out what multiplier you would need by looking at a few different device screen sizes to see if it's constant (e.g. iPhone 6, SE etc). But it may be more practical in the long run to use your own subclasses. Note you generally do want to use relative constraints for things like this, since your constant margins might look fine on one screen size but weird on another.
This is not ideal but technically you could also check what device the user is using (or what the view's width is) and return an appropriate constraint using a switch. Although, if you really are only concerned about the iPhone X vs the 6+, then you might want to consider doing that.
You might also want to consider using a form library like Eureka but there's a bit of a learning curve with anything like that, especially when it comes to customizing the appearance of cells and their subviews.

Why might Autolayout constraints not appear at runtime?

I am trying to create a custom subclass of UITableViewCell that displays an image and a few labels to the right of the image. I have my UIImageView and UILabels arranged in stack views, the outermost of which I pinned to all four sides of the content view.
But when I run the app in the simulator, I do not see the image views. Debugging the view hierarchy, I see they are getting clipped.
And digging in a little further by focusing on the outermost stack view with "Show Constraints" on, I don't see my auto layout constraints at all (instead I get an ambiguous position runtime warning for each of the outermost stack views).
The text label that expands to the right is set up with 0 lines and the table view gets a constant estimatedRowHeight value and its rowHeight set to UITableViewAutomaticDimension, so I think if these constraints were working, the rows in the table would size to fit the content. Perhaps notably, any width or height auto layout constraint I add does appear when I debug the view hierarchy, so I know some constraints are present at runtime, I just cannot for the life of me figure out why the constraints relative to the content view are not.
After wrestling with this for a long time and having a much more experienced developer look over my project, it seems as if there was nothing wrong with the way it was set up. Recreating the table view cell from scratch with exactly the same layout and constraints and using the exact same code fixed this issue. I had messed around with the stack views and constraints quite a bit before this started happening, so it might be possible to get Xcode into a place where it does not properly set up constraints when you run the app in the simulator.
Try to solve all warnings which are printed into your console log when you run your application and viewing this screen. Because you can not ignore warnings always, many warnings you must have to remove by correcting or solving issues in your constraint. And that is the only solution which helps you most of the time.
I'm 5 years late to the party, but I managed to find a solution to this problem in my project. If any of the views that are contained in the table view cell have a bad subclass set on them, the intializer defaults them back to a regular UIView and without any of the layout constraints. Hopefully that saves someone the hours it took me!

Auto Layout: Displaying content relative to container

I'm having some issues developing an iPhone application. I have a UITableView on a screen and have made a template for how I want to lay things out. I made sure that the constraints are satisfied and when my program compiles, I get no auto layout issues. However, when I run my program on the simulator, some of the text is not shown but I know it should be there. Here is how things look on the Storyboard:
However, this is how things look when I run the program on the iPhone simulator, it appears as so:
I am only worried about the From Date and To Date fields not being displayed because if I move them more to the left, I can eventually see them. Moreover, I made sure to make the To Date field's Trailing Space to Container Marginby 8 px so I don't really understand why these two fields aren't showing. Any help would be appreciated. Thanks!
Edit: Image of To Date constraints:
Edit 2: Image of how table view cell looks like now:
Most likely the labels are not showing because of size classes and the difference between the different screen sizes. In your story board the original view controller is a square shape. Make sure to pin the labels to the side of the cell that you want them to attach to. This will make sure they stay where you want them to. Also make sure that you pin the actual table view to the superview so you can see the labels. I have always pinned to the top, bottom, and both sides, to accommodate different screen sizes and rotation. You may need to change the constraints for the other size classes. This may make some things look they are bunched up a bit with the smaller screen size, but you can always change the font or the format of the cell to fit everything in.
If you want to change a constraint for another size class, just select that size class at the bottom of the story board. Select the label, and then in the size inspector you can make the constraints you don't want to be unable, and hook up some other constraints to make it work. Ray Wenderlich's web site has a great tutorial on size classes and adaptive layout. You can find it here.
Happy coding!!
Your "missing" labels are probably too far to the right, outside the screen boundaries. This could happen if your view controller is wider in the storyboard than when you run it. Make sure that your labels have constraints for trailing space -- that will cause them to always be within the screen bounds no matter the screen width.
Also, use the Debug View Hierarchy in Xcode to see where those labels actually end up.
UPDATE:
Try overriding awakeFromNib method in your UITableViewCell subclass:
override func awakeFromNib()
{
contentView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
}

Xcode 6 constraints for view in viewController fails

I´m pretty new to Xcode and playing around with some techniques.
For testing, i am writing an app where i have a detailViewController with three views within.
As soon as i assign constraints to one of the views the layout gets really strange. No matter if i center horizontally or set border distance, the view seems somehow to vanish and the components within the view are placed somehow.
Any idea what i´m doing wrong?
Sure, you need to follow these basic rules. Checkout the auto layout guide. Each view from the top of the scene to the bottom should have constraints (also constraints should exist from side-to-side if you want expansion and contraction, or have height/width if those are important to maintain). Most times you will need to have at least four constraints per view. The auto layout errors will not go away until all the views have constraints applied and adhere to the simple rules I mentioned above.

Centering Objects From Storyboard

Im starting to experiment with storyboard. As you can see I have chosen the storyboard size to be height=regular and width=compact, which says “For all iPhones in portrait”.
The simulator I am using is iPhone6 however when I run everything is slightly off to the right.
Can someone explain what is happening or what I am missing?
The problem is that (as described in the comments) you are positioning the views without AutoLayout. When you just drag and drop the views, it's actually setting the frame's positions and sizes. The main problem with this approach is that it doesn't set the position and size in a proportional and related manner, taking in consideration the container. This is why you're getting the view at the current position. If you run in another simulator, maybe you can get the correct position, or maybe not. What you can do to change this is apply auto layout constraints to those views. There's a special constraint to center views horizontally. With autoLayout you can go further, specifying relation between one or more views, and those views not necessarily need have the same container view.
One quick example:
Notes:
I'm using universal storyboard to take those screenshots. It's more flexible and with AL you don't necessarily have to concern yourself with the size, as views adjust themselves depending on the constraints applied to.
EDIT:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/Introduction/Introduction.html
This is a link to auto layout guide provided by apple, a great tutorial on how to get your hands dirty in this little world.

Resources