3

To make proper animation of a uiview with constraints u must set the new constraint value and then call theView.layoutIfNeeded() , for swift 3 this doesnt work and instead of calling from the view's whos constraint is changed . it must be called from the upper view like this : self.view.layoutIfNeeded(). ex :

UIView.animate(withDuration: 0.1,
               delay: 0.1,
               options: UIViewAnimationOptions.curveEaseIn,
               animations: { () -> Void in
                   constraintHeight.constant = 10.00
                   // instead of myView.layoutIfNeeded() // Swift 2
                   self.view.layoutIfNeeded() // Swift 3
    }, completion: { (finished) -> Void in
    // ....
})

The problem is, in my case i did the change and the way im using this animation is for a bottomview (a bottom bar/ banner view) that hides when scrolling a tableview down and comes up when going all the way to the top in the tableview. now that i have changed the proper code for swift 3 using self.view.layoutIfNeeded() , the tableview acts wierd, slows down, rows start appearing as fading in or is just way slow to present, when scrolling down and up the tableview's sections comes jumping or moving in slow motion, also have seem memory gone up from 80mb to 100mb . if i eliminate the line in the code, i dont get the animation, the view just appears and dissapears with the scrolling of the tableview, but... i dont get the strange behavior. i have also checked the views hierarchy to check somehow is not creating wierd 100 views replicating or something.. any hints on how can i fix this . all of this was just working fine in swift 2 using theView.layoutIfneeded() but now that the call is being madein the upper view.. omg..wierd acting

Question comes from Swift 3 UIView animation solution.

Community
  • 1
  • 1
lorenzo gonzalez
  • 1,894
  • 4
  • 14
  • 18

3 Answers3

5

Try this to force layout changes to superview

//Force to complete all changes.
self.view.superview.layoutIfNeeded()

//Update constant
constraintHeight.constant = 10.00

UIView.animate(withDuration: 0.1,
               delay: 0.1,
               options: UIViewAnimationOptions.curveEaseIn,
               animations: { () -> Void in
                   self.view.superview.layoutIfNeeded()
    }, completion: { (finished) -> Void in
    // ....
})
Bhavin Bhadani
  • 22,224
  • 10
  • 78
  • 108
  • this would be the Correct semantic way to say i need to layout thisView by calling the method on the super view. :D. in my case was still messing up my uitableview as all the views were on the same level the superview view being the root view , which also hosts the uitableview. Finally had to make a containerBottomView – lorenzo gonzalez Oct 22 '16 at 13:32
1
UIView.animate(withDuration: 0.5, delay: 0.3, options: [.repeat, .curveEaseOut, .autoreverse], animations: {
   // perform your animation here .
    self.username.center.x += self.view.bounds.width
    self.view.layoutIfNeeded()
}, completion: nil)
LinusGeffarth
  • 27,197
  • 29
  • 120
  • 174
Himanshu Moradiya
  • 4,769
  • 4
  • 25
  • 49
  • correct way is self.whateverView.superview?.layoutIfNeeded() , but take in count the view hierarchy, for my needs i had to create a container view. so it wouldnt trigger on the root view which also hosts the uitableview, for worst as i was calling this taking in count scroll , it pratically always being called. thus. it was always trying to layout everything from the root view down . check my final answer :d in case u have the same issue one day.. thanks for sharing – lorenzo gonzalez Oct 22 '16 at 13:36
1

Solution to my needs . thanks all for sharing your answers!.

my view hierarchy

- root view
   - uitableView
   - bottomBarView
   - bottomBannerView

Beacause of that hierarchy i couldnt use self.view.layoutIfNeeded() or self.bottomBarView.superview?.layoutIfneeded(), as it was calling to layout the same superview which also host the tableview and for which im triggering this function if scrolling is more than 10 and also if it less.. so its always trigerring the layoufIfneededmethod. i had to do what i thought from the beginning.

The correct way is to make a container view hosting the bottombarview and the banner view, have it constraint to bottom of the root super view and constraint the bottomBarView and bottomBannerView to IT.

View hierarchy now is .

-root view
  -uitableView
      -containerBottomView
           -bottomBarView
           -bottomBannerView

This way i can call self.bottomBarView.superview?.layoutIfNeeded() , and it wont be triggering on the root view which also host the uitableview. it correctly triggers to layout the containerBottomView.

lorenzo gonzalez
  • 1,894
  • 4
  • 14
  • 18