Xcode/Stackview, empty labels freaks out in stack view? - ios

hopefully an easy one here. I have some labels and text fields. Between them, I want some empty labels, which will if needed to be error texts. But when I try to stack view it all, Xcode zooms out and nothing can be seen on the viewController.
Anything else I need to change for it to work?
You can see a picture of it here before I hit stack view:
The email label and text field are already in stack view, so are passwords, gentag passwords and label/button.

This certainly appears to be a bug. I duplicated your issue. I was able to solve it by setting a height/width to each empty spacer label, prior to adding it to my stack view. This doesn't make sense because when you add an object to a stack view it loses all of the constraints it has. None the less it resolved the issue:

Sounds like its just an auto layout issue (or lack of). Can be really messy, best to just keep playing around.
As you've already done, I would first put each label and its text field in a horizontal stack view and add constraints.
Then I'd add each of these stackviews to their individual warning labels in a vertical stackview and add constraints.
Finally I would combine all of the stackviews into one vertical stackview!

Related

Xcode - Vertical Stack of Horizontal Stacks constraints

I'm very new to using Interface Builder and Auto Layout so please bear with me.
I'm trying to lay out a vertical stack of horizontal stacks, with each horizontal stack being made up of a label and another horizontal stack of two labels. The whole vertical stack is wrapped in another view that has 10 points left and right constraints. I want the two stack elements of each horizontal stack to be at the edges of the stack.
I can get the layout to look how I want it on the interface builder but when I run it, the Sunrise AM/PM label gets cut off.
Storyboard next to simulator instance where AM label is truncated
View hierarchy with constraints
Please let me know if there's anything unclear about what my goal or my issue is.
The Problem is that your programm does need to truncate something to fit everything on the screen. Since you probably did not define which element to truncate (by altering the compression resistance) it takes the last one in the stack - the am/pm one. Changing the compression resistance should fix this.
Check out this guide to learn about it.

IOS/Storyboard/Autolayout. Center horizontal group of elements

Using autolayout in Storyboard, is there a straightforward way to center a group of elements without making them part of a subview?
For example if I have one label 50 and a second element Points, is there a way to hold them together as one and then center it.
Right now, I am able to hold the space between them constant (as it needs to be) and horizontally align but I can't get the two of them together centered. My approach has been to set a leading space before the first element and a trailing space after the second element, but something is throwing it off. I know I could combine them into one label and center it, but I'm looking for a solution that I can reuse every time I have one of these all too common situations.
Thanks for any suggestions.
Image:
Storyboard.
This scenario is very common and very simple to solve: just get rid of the leading and trailing constraints and instead add horizontalCenter to the first label regarding the view. After that all you gotta do is adding horizontalCenter to the second one regarding the first and you're set! Now both of them are linked together and well centered.
If you need more help with this, just share your repo and I'll fork it.
I know your question specified that you don't want to make the two labels part of a subview, but I'm not aware of a good way to do that and thought I would at least mention that the standard / recommended way to handle this situation would be to add "3K" and "Points" to a horizontal stack view, and then horizontally center the stack view and vertically constrain it to "Explorer" above.
This would ultimately require the same or less constraints as what you have now because you wouldn't need to create constraints for the labels inside the stack view.
See Apple references here:
https://developer.apple.com/videos/play/wwdc2015/218/?time=134
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/LayoutUsingStackViews.html

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!

Autolayout vertical spacing of group of textlabels when one is empty

I have a group of text labels that are vertically spaced to each other 15 pixels.
The problem is that when one of the labels is empty, then there is extra space between the other two labels above and below the empty one (30 pixels).
I know that one solution would be to constraint all the text labels to the top and to the labels above and then I can just delete it and everything should look aligned but the problem is that I reuse the view and sometimes all the labels have text and sometimes some are empty. So if I delete the label, I would have to recreate it and readjust the constraints manually.
Is there a way to delete the extra vertical spacing when one of the labels is empty without deleting it?
Edit 1: The labels don't have any Height constraint so the empty one will be 0 pixels high
Edit 2: I need to support iOS7+
Possible options:
do not use multiple labels, but a single one, possibly using an attributed string if you need different formatting for the different parts
add an outlet to each of your constraints, and adjust the constant based on the label having text or not
There are quite a few others, including the use of table views, stack views (iOS 9+), and probably more...
If you are ok with supporting iOS 9 and above then you can use stack view and set the constraints for the labels within the stack view. But instead of emptying the label you should hide the label. When the label is hidden the stack view automatically brings up all the labels below it. You should get the desired behaviour using this method.
My rule of thumb is if layouts get overly complicated to do in Interface Builder, then it's better to just write code to do it. In this case I'm not even sure it's possible to define in IB. But even if it was, I'd do it in code. It's not a complicated layout, it will be more reusable, it will be cleaner in code.
A few options:
A - You could modify constraints in viewWillLayoutSubviews - it's kinda messy to hold on to so many top constraints. Somewhat less messy if you add them all to an outlet collection (array of outlets, basically).
B - You could manually adjust frames in viewDidLayoutSubviews - although it then begs the question, why even use AutoLayout at all if you're doing almost all the work manually anyway.
C - Use SnapKit and generate those constraints in viewDidLoad and / or update them whenever the text changes. I highly recommend SnapKit. Think of it as a sane way of programmatically creating AutoLayout constraints. It's very clean, and very simple.
See http://snapkit.io

Adding/removing views dynamically with autolayout

I have a pretty complex view and am trying to update it to work with autolayout (while I learn autolayout at the same time). Here is a screenshot of my view:
The only thing that you can't see is that all of these views are wrapped in a containerView and that container is sitting in a vertical scrolling UIScrollView.So if there was a really long description or something you would be able to scroll vertically.
My first problem is that I can't figure out how to get the descriptionView (red background) to adjust it's height dynamically (I have scrolling disabled in IB and again in code). I think it might be related to the bottom constraint to the imageScrollView.
The second problem is that the imageScrollView needs to be removed half the time. It holds multiple pictures of an item. But sometimes the item doesn't have pictures so I just want to remove the scrollView in that instance. I call removeSubview in code and want things to just readjust without having to set up a bunch of new constraints. So I added a top space constraint from the Question/Comments label to the bottom of the description and changed its priority to 900 instead of 1000. This seemed to solve my first problem and when I remove the imageScrollView the description view resized to the size of the content. However my scrollView that holds all of the content didn't scroll anymore, I am assuming that the containerView's height got screwed up or something.
Edit: the more I think about this the more I think that figuring out how to add a contraint for the size the descriptionView's height to match the content will solve the other problem as well. Here is another screenshot with the current constraints.
SOLUTION
I don't feel it is fair to post my own solution as the accepted answer. So I am posting my solution within the question, and giving the accepted answer to Nikita for trolling all the questions related to textViews being sized to their content.
My first problem is solved by using this: Github - Resizable Text View
The second issue was just a matter of setting up the constraints correctly. The red textView had a constraint to the bottom of the superview(contentContainer) (the superview which sets the height of the the main scrollView.) So when I removed textView then the contentContainer view didn't have a height constraint. So I ended up removing the constraint from the textView to the superview (which is the contentContainer) and made a constraint from the bottom of the commentTextView to the contentContainer. This solved the problem. Whenever I remove the red textView everything shrinks up the way I desire.
I'm not sure, that my solution is the best one, but I've done it in the following manner (I think that will help you with red text view): How do I size a UITextView to its content?
Unfortunately, I didn't understand you about second problem. Please, provide more details. Thanks!
Don't remove the image view. Just give it a zero-height constraint. That way you don't have to mess with any of your other constraints.

Resources