Search code examples
swiftuiviewcontrollerfadeinfadeout

No buttons/labels/anything will re-appear after I set alpha back to 1.0


What I want: After the Viewcontroller is called, I want to fade in all my elements in this Viewcontroller, except for the background. The background must stay.

What goes wrong: As you see in my code, for something to fade in, it first needs to be removed. The remove part is doing great. But, when I want it to re-appear, nothing happens. When I use the print function to see the alpha of a random label, it is set to 1.0. I can not figure out what I am doing wrong.

This is my code:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    Removeeverything()
    Fadein()
}

func Removeeverything() {
    for view in self.view.subviews as [UIView] {
        if let btn = view as? UIButton {
            UIView.animateWithDuration(0.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {

                btn.alpha = 0.0

                }, completion: nil)
        }
    }
    for view in self.view.subviews as [UIView] {
        if let btn = view as? UILabel {
            UIView.animateWithDuration(0.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {

                btn.alpha = 0.0

                }, completion: nil)
        }
    }
    for view in self.view.subviews as [UIView] {
        if let btn = view as? UIImageView {
            UIView.animateWithDuration(0.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {

                btn.alpha = 0.0

                }, completion: nil)
        }
    }
}

func Fadein() {
    Backgrond.alpha = 1.0
    for view in self.view.subviews as [UIView] {
        if let btn = view as? UIButton {
            UIView.animateWithDuration(1.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {

                btn.alpha = 1.0

                }, completion: nil)
        }
    }
    for view in self.view.subviews as [UIView] {
        if let btn = view as? UILabel {
            UIView.animateWithDuration(1.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {

                btn.alpha = 1.0

                }, completion: nil)
        }
    }
    for view in self.view.subviews as [UIView] {
        if let btn = view as? UIImageView {
            UIView.animateWithDuration(0.7, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {

                btn.alpha = 1.0

                }, completion: nil)
        }
    }

}

Solution

  • I'd say that the problem is that UIView.animateWithDuration is executed asynchronous (that is - your fadeIn() function will execute before the animations in removeEverything() are complete).

    Simply remove the UIView.animateWithDuration operations from your Removeeverything(). Since you've set the duration argument to 0.0 nothing will really change (except that the code should now work)

    func removeEverything() {
        for v in view.subviews.filter({ $0 is UIButton || $0 is UILabel || $0 is UIImageView }) {
            v.alpha = 0
        }
    }
    
    func fadeIn() {
        // Background.alpha = 1.0
        UIView.animateWithDuration(1.0, delay: 0, options: .CurveEaseIn, animations: {
            for v in view.subviews.filter({ $0 is UIButton || $0 is UILabel }) {
                v.alpha = 1
            }
        }, completion: nil)
        UIView.animateWithDuration(0.7, delay: 0, options: .CurveEaseIn, animations: {
            for v in view.subviews.filter({ $0 is UIImageView }) {
                v.alpha = 1
            }
        }, completion: nil)
    }
    

    That code snippet should work as expected. I used the filter function on the array and got rid of a couple of unnecessary casts to make the code more readable. Hope it helps!