【问题标题】:swift 3 layoutIfneeded not working properlyswift 3 layoutIfneeded 无法正常工作
【发布时间】:2024-01-19 16:10:01
【问题描述】:

要使带有约束的 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 解决方案。

【问题讨论】:

    标签: ios animation uiview swift3 uiviewanimation


    【解决方案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,以防你有一天遇到同样的问题。谢谢分享