正在跳过UIView动画

时间:2018-06-13 21:28:37

标签: ios swift uiviewanimation

Ok快速背景:我正在两个控制器之间进行搜索:我的家庭控制器和一个具有地图视图的控制器。当用户点击搜索栏的textField

时会触发segue

我已经包含了动画前后的图像

Before: HomeController

After: PlacesController

流程如下:

我将搜索栏添加到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()

这里没问题。另外:搜索栏之前已激活高度约束:heightAnchor.constraint(equalToConstant: PlacesSearchView.height).isActive = true

下一步是这个动画(自定义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)
}

非常简单,再没问题

这部分是问题:

我停用旧的搜索栏限制:

NSLayoutConstraint.deactivate(preConstraints)

我创建了关闭按钮并将其锚定到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

然后我将新约束应用于搜索栏。

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

锚定键盘:

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

instantiateTableView()
subviewTableView()

然后我当然应用了神奇的公式:

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

但是!令我惊讶的是......它会跳过动画。直奔最终状态。就像直接到图片2.我试图做(愚蠢)的东西让某种动画进行一次(比如我用这个简化版测试:没有添加也没有停用任何约束,只是尝试将topConstraint.constant更改为0和......同样的事情:搜索栏直接向上,没有任何动画)

我没有得到什么?感谢您对我的回答,我期待您的见解!

更新:出于某种原因,我忘了将最后一个UIView.animate块放在DispatchQueue.main.async块中。这样做会导致...有时会有动画而大多数时候都没有动画。这变得越来越奇怪了。另外,在此之前,我从来没有把动画放在DispatchQueue.main.async块中,即使在其他自定义段中也是如此,这也很奇怪。

1 个答案:

答案 0 :(得分:0)

好的我明白了,这就是发生的事情:

基本上...... DispatchQueue.main.async是问题的根源。让我解释一下。

首先,让我们清楚,我在DispatchQueue.main.async区块内执行segue:

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

但显然......这还不够。

然后我有了将override func perform()代码放在DispatchQueue.main.async内的想法(是的......我知道!)。所以它看起来像这样:

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

而且......每次都是动画!

动画很奇怪所以我基本上决定尝试在块中放置不同部分的代码,直到它工作并且...它最终起作用。 (我承认这样做的一种耻辱)。现在感兴趣的人详情如下:

  • 如果用户点击了searchButton,则有一部分代码负责制作动画。这在将整个perform()代码放在DispatchQueue.main.async块中之前有效,所以...我回滚到工作版本
  • 现在对于负责动画的部分,如果用户点击了textField:它现在基本上看起来像这样(segueToEditing是我创建closeButton,删除旧约束,添加新约束和动画):

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

我仍然对我的解决方案如何运作感到困惑,但我现在知道我不会混淆DispatchQueue.main.async块。