【问题标题】:The completion block of UIView animation gets called before the animation is finishedUIView 动画的完成块在动画完成之前被调用
【发布时间】:2018-07-14 11:41:42
【问题描述】:

我有一个用于view controller 交互式过渡的自定义动画师。还有一个blur effect,根据转换进度设置为nil。效果的动画代码如下:

@objc func blurEffectDissmisal() {

    UIView.animate(withDuration: dismissAnimator.durationOfAnimation + 1, animations: {
        self.blurEffectView?.effect = nil
    }) { (done) in
        if (done) {
       self.blurEffectView?.removeFromSuperview()
        }
    }
}

我用notification 调用它,当从第二个view controller 开始转换到第一个时,它会调用它。

但是,我这里有个问题。在动画结束之前调用完成块。当我第一次运行转换时(没有取消它)它工作正常,但在随后的运行中它没有。

我也曾尝试将动画添加到我的动画师中,但也没有成功。

此外,当我取消转换时,完成块在实际动画结束之前被调用(在这种情况下,我理解为什么但不知道如何让它向后移动。也许我应该在完成块?)

如您所见,我已尝试来自 answer 的建议,但没有帮助。

如果您知道如何解决此问题,我将非常感谢您的帮助。

【问题讨论】:

  • 澄清一下,代码按预期运行,但将实例设置为 nil 无法动画...
  • 我添加了答案,请检查并在操场上尝试,如果它解决了您的问题,请将其标记为最佳答案。如果您有任何问题,请在我的回答下方提问。

标签: ios swift uiviewcontroller uiviewanimation


【解决方案1】:

在调用 animate 函数之前使用延迟。

        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
        UIView.animate(withDuration: 2.0,delay: 0, animations: {
            self.frame.origin.x = -2000
        }) { (done) in
            if(done){
                self.removeFromSuperview()
            }
            
        }
    }

【讨论】:

    【解决方案2】:

    我创建了一个 Playground,您可以在其中查看此更改,只需创建新 Playground,单击助手编辑器(左上角,两个相连的圆圈)并查看动画。这应该做。

    import PlaygroundSupport
    import UIKit
    
    
    let rect = CGRect(x: 0, y: 0, width: 40, height: 40)
    let view = UIView(frame: rect )
    view.backgroundColor = UIColor.yellow
    let label = UILabel(frame: rect)
    label.text = "A"
    label.textAlignment = .center
    view.addSubview(label)
    
    let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame = view.bounds
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    view.addSubview(blurEffectView)
    
    PlaygroundPage.current.liveView = view
    
    UIView.animate(withDuration: 4, animations: {
        blurEffectView.alpha = 0
    }) { (done) in
        if (done) {
            blurEffectView.removeFromSuperview()
        }
    }
    

    您面临的问题不是 UIView.animate 没有完成它的工作,而只是因为您将视图设置为 nil 是不可动画的。就像想象删除某些东西可以动画一样......

    【讨论】:

    • 是的,你是对的。当然,我不想动画化从超级视图中移除效果。问题是在动画完成之前调用了完成块。但是,我发现我没有从NotificationCenter 中删除observer。但是,当取消转换时,我仍然有从超级视图中删除效果的问题。在这种情况下,应该播放动画而不是移除模糊效果。
    • 使用委托或 KVO 总是比使用通知中心更好,这样的事情可能会发生......你可以做的是在动画结束时将 userInteractionEnabled 设置为 false 并且当你想要它返回时再次设置为 true 以忽略用户的点击...
    • 感谢您的建议。我使用的是委托而不是Notification Center,但是后来我认为Notification Center 在代码行的情况下不那么冗长,所以我决定使用这种技术。无论如何,谢谢你的建议。我在第一个view controller 中有一个表格视图,所以当模糊效果消失时,用户应该能够与之交互。但老实说,我不太明白你说的是哪个视图的userInteractionEnabled 属性。你能澄清那部分吗?
    • 好吧,我好像一开始没有得到这个问题。我认为您可能想要重用模糊添加/删除,因此将 blurView 的 alpha 值设置为 0 和 userInteractionEnabled 设置为 false 可能是合适的(不是内存效率),因为当您设置它时,触摸识别器进入下一层。
    • 是的,在这种情况下,将 viewalpha 值设置为 0 不会节省内存,因为第一个 viewController 非常重(如果有多个视图),因此最好从层次结构中删除 blurEffectView。目前,我正在尝试解决在取消转换时视图从层次结构中移除的问题。也许您对播放blurEffectView 的动画有一些建议,因为我不知道如何解决这个问题?
    【解决方案3】:
      UIView.animate(withDuration: 1, animations: {
                    self.blurEffectView?.frame = CGRect(x: self.blurEffectView?.frame.origin.x, y: self.view.frame.size.height, width: self.blurEffectView?.frame.size.width, height: self.blurEffectView?.frame.size.height)
                }, completion: {
                    (value: Bool) in
                    self.blurEffectView?.removeFromSuperview()
                })  
    

    使用相同的动画(在 UIView 上)我能够做到这一点:

    【讨论】:

    • 对不起,但效果是一样的。你的第一个代码和我的一样(它只是不检查闭包中动画的完成情况),不是吗?
    • 您是否也尝试过第二个代码?因为我一直在用。它将视图从其原始位置滑动到屏幕底部,然后将视图从超级视图中删除
    • 你的第一个代码块和有问题的代码有什么区别,忽略了问题使用常量作为持续时间的事实?
    • 是的。老实说,我的第一个动画代码就是这样的,但我决定改变它(让模糊消失)。问题是,当我第一次运行转换时它工作正常,但是当我再次尝试时,在中途我的 blurEffectView 就消失了(通过完成块从其超级视图中删除)
    • 感谢您的回答。我的view 的行为与此完全相同,但仅在我第一次运行动画时。不过,我已经解决了这个问题。这是因为我忘记删除NotificationCenter 的观察者。目前我正在解决第二个问题,即在取消转换时播放动画。
    猜你喜欢
    • 1970-01-01
    • 2014-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-11
    • 2013-02-13
    相关资源
    最近更新 更多