Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIStackView - layout constraint issues when hiding stack views

My app has 2 screens:

  1. TableViewVC (no stack views here)

  2. DetailVC (all the nested stack views here; please see link for picture: Nested StackViews Picture) -- Note, there are labels and images within these stack views.

When you press a cell in the tableview, it passes the information from the TableViewVC to the DetailVC. The problem is with hiding the specific UIStackViews in the DetailVC. I want only 2 stack views out of the various ones in the DetailVC to be hidden as soon as the view loads. So I write this code in the DetailVC to accomplish this:

override func viewDidLoad() {     super.viewDidLoad()      self.nameLabel.text = "John"      self.summaryStackView.hidden = true     self.combinedStackView.hidden = true } 

Everything looks great but Xcode give many warnings only at runtime. There are no warning in Storyboard when the app is not running. Please see link for picture of errors: Picture of Errors

Basically it's a lot of UISV-hiding, UISV-spacing, UISV-canvas-connection errors. These errors go away if I hide the same stack views in viewDidAppear but then there is a flash of the stuff that was supposed to be hidden and then it hides. The user sees the the view briefly and then it hides which is not good.

Sorry for not being able to actually post pictures instead of links, still can't do so.

Any suggestions on how to fix this? This is for an app I actually want to launch to the app store - it's my first so any help would be great!

Edit/ Update 1:

I found a small work around with this code which I put inside the second screen called DetailVC:

// Function I use to delay hiding of views func delay(delay: Double, closure: ()->()) {     dispatch_after(         dispatch_time(             DISPATCH_TIME_NOW,             Int64(delay * Double(NSEC_PER_SEC))         ),         dispatch_get_main_queue(), closure) }  // Hide the 2 stack views after 0.0001 seconds of screen loading override func awakeFromNib() {     delay(0.001) { () -> () in         self.summaryStackView.hidden = true         self.combinedStackView.hidden = true     } }  // Update view screen elements after 0.1 seconds in viewWillAppear override func viewWillAppear(animated: Bool) {     super.viewWillAppear(animated)     delay(0.1) { () -> () in         self.nameLabel.text = "John"     } } 

This gets rid of the warnings about layout constraints completely from Xcode.

It's still not perfect because sometimes I see a glimpse of the views that are supposed to be hidden -- they flash really quick on the screen then disappear. This happens so quickly though.

Any suggestions as to why this gets rid of warnings? Also, any suggestions on how to improve this to work perfectly??? Thanks!

like image 552
JEL Avatar asked Nov 11 '15 01:11

JEL


People also ask

How do I hide view in stack view?

In order to hide a view within a stack view, set the contained view's hidden property to true , and the stack view handles the rest. This is how you'll fix the spacing under the WEATHER label when the user hides the text below it.

How does Uistackview layout elements in a stack?

The stack view aligns the first and last arranged view with its edges along the stack's axis. In a horizontal stack, this means the first arranged view's leading edge is pinned to the stack's leading edge, and the last arranged view's trailing edge is pinned to the stack's trailing edge.

Can stack view be scrollable?

It's not necessary to combine manual and auto layout to allow for a scrollable stack view. You simply need to constrain the stack view's width and/or height.

When should I use Stackview?

Best use of stack view is that if you want to set multiple controls allinged vertically or horizontally to each other you just add all of them in stack view. stackview will handle its allignment you just need to give frame contraints to stackView.


2 Answers

I had the same problem and I fixed it by giving the height constraints of my initially hidden views a priority of 999.

enter image description here

The problem is that your stackview applies a height constraint of 0 on your hidden view which conflicts with your other height constraint. This was the error message:

Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)  (     "<NSLayoutConstraint:0x7fa3a5004310 V:[App.DummyView:0x7fa3a5003fd0(40)]>",     "<NSLayoutConstraint:0x7fa3a3e44190 'UISV-hiding' V:[App.DummyView:0x7fa3a5003fd0(0)]>" ) 

Giving your height constraint a lower priority solves this problem.

like image 170
Raphael Avatar answered Sep 28 '22 11:09

Raphael


This is a known problem with hiding nested stack views.

There are essentially 3 solutions to this problem:

  1. Change the spacing to 0, but then you'll need to remember the previous spacing value.
  2. Call innerStackView.removeFromSuperview(), but then you'll need to remember where to insert the stack view.
  3. Wrap the stack view in a UIView with at least one 999 constraint. E.g. Top, Leading, Trailing @ 1000, Bottom@999.

The 3rd option is the best in my opinion. For more information about this problem, why it happens, the different solutions, and how to implement solution 3, see my answer to a similar question.

like image 21
Senseful Avatar answered Sep 28 '22 12:09

Senseful