Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView.animateWithDuration Not Animating Swift (again)

Note: I’ve already checked the following stack overflow issues:

27907570, 32229252, 26118141, 31604300

All I am trying to do is fade animate in a view (by alpha) when called by an IBAction attached to a button. Then reverse when a button on the view is hit.

My wrinkle may be that I'm using a secondary view that is on the ViewDock in the storyboard View. The view is added to the subview at the time of viewDidLoad where the frame/bounds are set to the same as the superview (for a full layover)

The reason this is done as an overlay view since it is a tutorial indicator.

The result (like many others who've listed this problem) is that the view (and contained controls) simply appears instantly and disappears as instantly. No fade.

I have tried animationWithDuration with delay, with and without completion, with transition, and even started with the old UIView.beginAnimations.

Nothing is working. Suggestions warmly welcomed.

The code is about as straight forward as I can make it:
Edit: Expanded the code to everything relevant
Edit2: TL;DR Everything works with the exception of UIViewAnimateWithDuration which seems to ignore the block and duration and just run the code inline as an immediate UI change. Solving this gets the bounty

@IBOutlet var infoDetailView: UIView! // Connected to the view in the SceneDock  override func viewDidLoad() {     super.viewDidLoad()      // Cut other vDL code that isn't relevant      setupInfoView() }  func setupInfoView() {     infoDetailView.alpha = 0.0     view.addSubview(infoDetailView)     updateInfoViewRect(infoDetailView.superview!.bounds.size) }  func updateInfoViewRect(size:CGSize) {     let viewRect = CGRect(origin: CGPointZero, size: size)      infoDetailView.frame = viewRect     infoDetailView.bounds = viewRect      infoDetailView.layoutIfNeeded()     infoDetailView.setNeedsDisplay() }  override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {     super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)     updateInfoViewRect(size) }  func hideInfoView() {     AFLog.enter(thisClass)     UIView.animateWithDuration(         2.0,         animations:         {             self.infoDetailView.alpha = 0.0         },         completion:         { (finished) in             return true         }     )     AFLog.exit(thisClass) }  func showInfoView() {     AFLog.enter(thisClass)     UIView.animateWithDuration(         2.0,         animations:         {             self.infoDetailView.alpha = 0.75         },         completion:         { (finished) in             return true         }     )     AFLog.exit(thisClass) }  // MARK: - IBActions  @IBAction func openInfoView(sender: UIButton) {     showInfoView() }  @IBAction func closeInfoView(sender: UIButton) {     hideInfoView() } 

Please note, I started with the following:

func showInfoView() {     UIView.animateWithDuration(2.0, animations: { () -> Void in         self.infoDetailView.alpha = 0.75     }) }  func hideInfoView() {     UIView.animateWithDuration(2.0, animations: { () -> Void in         self.infoDetailView.alpha = 0.00     }) } 
like image 284
Dru Freeman Avatar asked Apr 05 '16 20:04

Dru Freeman


Video Answer


1 Answers

If you infoDetailView is under auto layout constraints you need to call layoutIfNeeded on the parent view inside animateWithDuration:

func showInfoView() {     self.view.layoutIfNeeded() // call it also here to finish pending layout operations     UIView.animate(withDuration: 2.0, animations: {         self.infoDetailView.alpha = 0.75         self.view.layoutIfNeeded()     }) } 

Theoretically this should not be needed if you just change the .alpha value, but maybe this could be the problem in this case.

like image 86
Darko Avatar answered Sep 19 '22 08:09

Darko