Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StackView isHidden attribute not updating as expected

I'm trying to update a UIStackView so that a field displays, should the value of a UITextField equal "Other". Here is my code:

@IBOutlet var stackView: UIStackView!
func updateView() {
    print("UPDATING")
    UIView.animate(withDuration: 0.25, animations: { () -> Void in
         if(self.myTextField.text! == "Other") {
              print("SHOWING")
              self.stackView.arrangedSubviews[3].isHidden = false
         } else {
              print("HIDING")
              self.stackView.arrangedSubviews[3].isHidden = true
         }
         print("Is hidden: \(self.stackView.arrangedSubviews[3].isHidden )")
    })

An example output looks like this:

> UPDATING
> HIDING
> Is hidden: true
> UPDATING
> SHOWING
> Is hidden: true

As you can see, the isHidden attribute is reported as true, regardless of what the code above has set it to. I can't really figure out why that might be, but perhaps someone on here can? Is there something obvious to check? Is there any reason why isHidden can't be updated? (note there are no errors appearing in the output).

like image 709
Ben Avatar asked May 07 '17 12:05

Ben


2 Answers

It's known UIStackView bug (http://www.openradar.me/25087688). There is a thread on SO about it: (Swift: Disappearing views from a stackView). Long story short:

The bug is that hiding and showing views in a stack view is cumulative. Weird Apple bug. If you hide a view in a stack view twice, you need to show it twice to get it back.

To fix this issue you can use following extension:

extension UIView {
    var isHiddenInStackView: Bool {
        get {
            return isHidden
        }
        set {
            if isHidden != newValue {
                isHidden = newValue
            }
        }
    }
}
like image 185
Timur Bernikovich Avatar answered Oct 19 '22 03:10

Timur Bernikovich


Updates on the user interface always have to be done on the main thread (THE LAW).

So wrap you UI updates on the main thead:

@IBOutlet var stackView: UIStackView!
func updateView() {
    print("UPDATING")
    UIView.animate(withDuration: 0.25, animations: { () -> Void in
        DispatchQueue.main.async {  // UI updates on the main thread
            if(self.myTextField.text! == "Other") {
                print("SHOWING")
                self.stackView.arrangedSubviews[3].isHidden = false
             } else {
                print("HIDING")
                self.stackView.arrangedSubviews[3].isHidden = true
             }
             print("Is hidden: \(self.stackView.arrangedSubviews[3].isHidden )")
        }
    })
like image 25
zisoft Avatar answered Oct 19 '22 01:10

zisoft