swift 3 layoutIfneeded 无法正常工作

Posted

技术标签:

【中文标题】swift 3 layoutIfneeded 无法正常工作【英文标题】:swift 3 layoutIfneeded not working properly 【发布时间】:2016-10-19 12:55:31 【问题描述】:

要使带有约束的 uiview 正确动画,您必须设置新的约束值,然后调用 theView.layoutIfNeeded() ,for swift 3 这不起作用,而不是从视图的 whos 约束中调用被改变了。它必须像这样从上视图调用:self.view.layoutIfNeeded()。 例如:

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
    // ....
)

问题是,在我的情况下,我进行了更改,我使用此动画的方式是用于底部视图(底部栏/横幅视图),它在向下滚动 tableview 时隐藏并在一直到在 tableview 顶部。现在我已经使用 self.view.layoutIfNeeded() 更改了 swift 3 的正确代码,当向下和向上滚动 tableview 的部分时,tableview 行为怪异、变慢、行开始淡入或呈现速度很慢以慢动作跳跃或移动,似乎内存也从 80mb 增加到 100mb 。如果我消除代码中的行,我没有得到动画,视图只是出现并随着 tableview 的滚动而消失,但是......我没有得到奇怪的行为。我还检查了视图层次结构以检查是否没有创建奇怪的 100 个视图复制或其他东西.. 关于如何解决这个问题的任何提示。所有这一切都在 swift 2 中使用 View.layoutIfneeded() 运行良好,但现在调用是在上视图中进行的.. omg..wierd 作用

问题来自Swift 3 UIView animation 解决方案。

【问题讨论】:

【参考方案1】:

试试这个来强制改变超级视图的布局

//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
    // ....
)

【讨论】:

这将是正确的语义方式,说我需要通过调用超级视图上的方法来布局 thisView。 :D。在我的情况下,我的 uitableview 仍然混乱,因为所有视图都在同一级别上,超级视图视图是根视图,它也托管 uitableview。最后不得不做一个containerBottomView【参考方案2】:

解决我的需求。谢谢大家分享你的答案!

我的视图层次结构

- root view
   - uitableView
   - bottomBarView
   - bottomBannerView

由于该层次结构,它不能使用 self.view.layoutIfNeeded() 或 self.bottomBarView.superview?.layoutIfneeded(),因为它正在调用布局相同的超级视图,该超级视图也托管 tableview 并且我触发了这个函数如果滚动超过 10 并且如果它更少.. 所以它总是触发 layoutIfneeded 方法。我必须按照我从一开始的想法去做。

正确的做法是做一个容器视图托管bottombarview和banner view,让它约束到root super view的底部,把bottomBarView和bottomBannerView约束到IT。

视图层次现在是 .

-root view
  -uitableView
      -containerBottomView
           -bottomBarView
           -bottomBannerView

这样我可以调用 self.bottomBarView.superview?.layoutIfNeeded() ,它不会在也托管 uitableview 的根视图上触发。它正确触发布局 containerBottomView。

【讨论】:

【参考方案3】:
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)

【讨论】:

正确的方法是 self.whateverView.superview?.layoutIfNeeded() ,但考虑到视图层次结构,为了我的需要,我必须创建一个容器视图。所以它不会在也托管 uitableview 的根视图上触发,最糟糕的是,因为我称之为计数滚动,它实际上总是被调用。因此。它总是试图从根视图向下布局所有内容。检查我的最终答案:d,以防你有一天遇到同样的问题。谢谢分享

以上是关于swift 3 layoutIfneeded 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

调用 layoutIfNeeded 后 Snapkit 3.0 无法获得正确的帧

swift 不确定 layoutIfNeeded setNeedsUpdateConstraints 或 updateConstraints setNeedsLayout

如何在 UIView swift 中重新加载特定的子视图?

layoutIfNeeded 是如何使用的?

IOS Swift 卡片效果图被剪裁了

覆盖 UILabel setText: Swift 中的方法