简体   繁体   English

UIView动画被跳过

[英]UIView animation is being skipped

Ok quick background: I am seguing between two controllers: my home controller and a controller that has a map as view. 好的快速背景:我正在两个控制器之间进行争夺:我的家庭控制器和一个具有地图视图的控制器。 A segue is triggerd when the user clicks on the textField of the search bar 当用户单击搜索栏的textField时触发segue

I have included images of before and after animation 我包括了动画前后的图像

之前:HomeController

之后:PlacesController

The process goes as: 该过程如下:

I add the search bar to let keyWindow = UIApplication.shared.keyWindow at the same position as it was in the table view 我添加了搜索栏, let keyWindow = UIApplication.shared.keyWindow与表视图中的位置相同

let preLeadingConstraint = searchView.leadingAnchor.constraint(equalTo: keyWindow.leadingAnchor, constant: 8)
let preTrailingConstraint = searchView.trailingAnchor.constraint(equalTo: keyWindow.trailingAnchor, constant: -8)
let preTopConstraint = searchView.topAnchor.constraint(equalTo: keyWindow.topAnchor, constant: originY)

NSLayoutConstraint.activate([preLeadingConstraint, preTrailingConstraint, preTopConstraint])
keyWindow.layoutIfNeeded()

No problem here. 没问题 Also: the search bar has a height constraint activated before that: heightAnchor.constraint(equalToConstant: PlacesSearchView.height).isActive = true 另外:搜索栏在此之前已激活了高度限制: heightAnchor.constraint(equalToConstant: PlacesSearchView.height).isActive = true

Next step is this animation (custom segue): 下一步是此动画(自定义segue):

UIView.animate(withDuration: self.duration, animations: {
    homeController.view.frame.origin.x = -Global.width
    self.destination.view.frame.origin.x = 0
}) { _ in
    homeController.navigationController?.viewControllers.append(self.destination)
    self.destination.navigationController?.setNavigationBarHidden(false, animated: true)
}

Very straightforward and again no problem 非常简单又没有问题

This part is the issue: 这部分是问题:

I deactivate the old search bar constraints: 我停用了旧的搜索栏约束:

NSLayoutConstraint.deactivate(preConstraints)

I create the close button and anchor it to keyWindow: 我创建关闭按钮并将其锚定到keyWindow:

let side: CGFloat = 25
let margin: CGFloat = 8

closeButton?.topAnchor.constraint(equalTo: keyWindow.layoutMarginsGuide.topAnchor, constant: margin).isActive = true
closeButton?.centerXAnchor.constraint(equalTo: keyWindow.centerXAnchor).isActive = true
closeButton?.heightAnchor.constraint(equalToConstant: side).isActive = true
closeButton?.widthAnchor.constraint(equalTo: closeButton!.heightAnchor).isActive = true

Then I apply new constraints to the Search Bar. 然后,我将新的约束应用于搜索栏。

topAnchor.constraint(equalTo: closeButton!.bottomAnchor, constant: yAxisMargin).isActive = true
leadingAnchor.constraint(equalTo: keyWindow.leadingAnchor, constant: 0).isActive = true
trailingAnchor.constraint(equalTo: keyWindow.trailingAnchor, constant: 0).isActive = true

And anchor to keyboard: 并锚定到键盘:

bottomKeyboardConstraint = bottomAnchor.constraint(equalTo: keyWindow.bottomAnchor, constant: -keyboardHeight)
heightConstraint.isActive = false
bottomKeyboardConstraint?.isActive = true

instantiateTableView()
subviewTableView()

Then of course I apply the magic formula: 然后,我当然会应用魔术公式:

UIView.animate(withDuration: 0.5, animations: {
    keyWindow.layoutIfNeeded() 
    // (I also animate background color)
}

BUT! 但! To my surprise... it skips the animations. 令我惊讶的是,它跳过了动画。 Goes straight to end state. 直接进入结束状态。 Like straight to picture 2. I tried to do (silly) stuff to have some kind of animation going one (like for example I tested with a simplified version of this: did not add nor deactivate any constraint and just tried changing topConstraint.constant to 0 and... same thing: the search bar goes straight up without any animation) 就像直接转到图片2一样。我尝试做一些(愚蠢的)事情,使某种动画效果得以实现(例如,我使用简化版的动画进行了测试:既未添加也未停用任何约束,只是尝试将topConstraint.constant更改为0和...是同一件事:搜索栏没有任何动画就直接向上移动)

What am I not getting? 我没有得到什么? Thanks for bearing with my answer and I look forward to your insights! 感谢您提供我的答案,我们期待您的见解!

Update: For some reason I have forgotten to put the last UIView.animate block in a DispatchQueue.main.async block. 更新:由于某种原因,我忘记了将最后一个UIView.animate块放入DispatchQueue.main.async块中。 Doing so results in... having an animation sometimes and no animations most of the time. 这样做会导致...有时有动画,但大多数时候没有动画。 This is becoming increasingly weird. 这变得越来越怪异。 Also, I never had to put any of my animations in a DispatchQueue.main.async block prior to that, even in other custom segues, which is also weird. 另外,在此之前,我甚至不必在DispatchQueue.main.async块中放置任何动画,即使在其他自定义脚本中也是如此,这也很奇怪。

Ok I got it, here is what's happening: 好的,我明白了,这是正在发生的事情:

Basically... DispatchQueue.main.async was the root of the problem. 基本上... DispatchQueue.main.async是问题的根源。 Let me explain. 让我解释。

First off, let's be clear, I perform the segue inside a DispatchQueue.main.async block: 首先,让我们清楚一点,我在DispatchQueue.main.async块内执行segue:

DispatchQueue.main.async {
     self.performSegue(withIdentifier: HomeViewController.storyboardData.segueIdentifiers.places, sender: self)
}

But apparently... it is not enough. 但是显然……这还不够。

I then had the idea of placing my override func perform() code inside a DispatchQueue.main.async (yes again... I know!). 然后,我想到将override func perform()代码放在DispatchQueue.main.async (再次是,我知道!)。 So it looked like this: 所以看起来像这样:

override func perform() {
    DispatchQueue.main.async {
        ...
    }
}

And... it was animating every time! 而且...每次都在制作动画!

The animations were weird so I basically decided to try placing different portions of code in the block till it'd work and... it eventually worked. 动画很怪异,所以我基本上决定尝试将代码的不同部分放在块中,直到它起作用为止。 (Kind of a shame to do this sort of thing I'll admit). (我承认这样做很可耻)。 Now for those interested the details are as follow: 现在,对于那些感兴趣的人,详细信息如下:

  • There is a portion of code responsible of animating in case the user clicked the searchButton. 有一部分代码负责在用户单击searchButton时进行动画处理。 This worked prior to placing the whole perform() code inside a DispatchQueue.main.async block so... I rolled back to the working version 在将整个perform()代码放入DispatchQueue.main.async块之前,此方法起作用了,因此...我回滚到工作版本
  • Now for the portion responsible of animating in case the user clicked the textField: It basically looks like this now (segueToEditing is where I create the closeButton, delete old constraint, add the new ones and animate): 现在,对于负责在用户单击textField时进行动画处理的部分:现在基本上看起来像这样(segueToEditing是我创建closeButton,删除旧约束,添加新约束并设置动画的位置):

    DispatchQueue.main.async { self.segueToEditing() }

I am still kind of confused by how my solution works, but I now know that I shall not mess with DispatchQueue.main.async blocks. 我仍然对解决方案的工作方式感到困惑,但是现在我知道我不会弄乱DispatchQueue.main.async块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM