当更改约束时,`self.view.layoutIfNeeded()`是用来做什么的?

16

所以我正在学习如何制作从屏幕外部动画出现的视图,以用作滑动菜单。

class ViewController: UIViewController {
    @IBOutlet weak var red: UIView!
    @IBOutlet weak var redHConstraint: NSLayoutConstraint!

    @IBAction func buttonShift(sender: AnyObject) {
        self.view.layoutIfNeeded()        // **HERE**
        UIView.animateWithDuration(0.5) {
            self.redHConstraint.constant = 0
            self.view.layoutIfNeeded()    // And **HERE**
        }
    }

}
我从如何在Swift中使用约束动画UIView?这里的代码进行了修改。
1. 代码中的 self.view.layoutIfNeeded()是做什么用的?
2. 为什么要在动画之前和之中分别编写两次?
注意: 如果我注释掉第一个 self.view.layoutIfNeeded(),则没有任何变化,但如果我注释掉第二个 self.view.layoutIfNeeded(),则移动将不再以动画方式进行,而只会出现在新坐标中。
1. 代码中的 self.view.layoutIfNeeded()是用来干什么的?
2. 为什么要在动画之前和动画期间分别写两次?
注意:如果我注释掉第一个self.view.layoutIfNeeded(),那么不会有任何改变,但如果我注释掉第二个self.view.layoutIfNeeded(),那么移动就不再有动画效果,而只会直接出现在新的坐标中。
1个回答

31

基本上,调用 self.view.layoutIfNeeded() 将强制布局 self.view 及其子视图,如果有一些更改集为 self.view 设置了 setNeedsLayout

setNeedsLayout 用于设置一个标志,每当调用 layoutIfNeeded() 时,就会调用 layoutSubviews。这是决定调用的 "如果需要" 方面。

如果您对 UIView 进行更改导致它 setNeedsLayout,但未调用 layoutIfNeeded()(因此未调用 layoutSubviews),则不会更新,因此可能会导致动画出现问题。如果您在运行动画之前调用它,则会确保如果有更改需要更新您的布局,则会将其应用于视图及其所有子视图,然后再进行动画。

当然,在进行动画时,您正在进行需要更新的更改。


所以首先要确保red:UIView中的所有“objects”都摆放好了?如果我注释掉第一个,“red”中的所有东西都会混乱吗? - Chameleon
如果你注释掉它,有可能会出现这样的情况:如果某些操作导致 self.view 发生变化并调用了 "setNeedsLayout" 但没有调用 self.view.layoutIfNeeded(),那么它将不会更新,从而可能会破坏你的动画。 - chrissukhram
@chrissukhram,感谢您的解释。一旦约束动画开始,我该如何暂停/停止它?我尝试过.removeAllAnimations(),它确实停止了动画,但也跳到了动画的结尾。我还尝试了使用很短的持续时间和选项启动另一个动画:UIViewAnimationOptions.BeginFromCurrentState(正如在SO的其他地方建议的那样),但这根本没有停止动画。谢谢。 - rockhammer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接