UIDynamicAnimator、removeAllBehaviors() 第一次不起作用

Posted

技术标签:

【中文标题】UIDynamicAnimator、removeAllBehaviors() 第一次不起作用【英文标题】:UIDynamicAnimator, removeAllBehaviors() doesn't work at first time 【发布时间】:2016-10-19 15:45:33 【问题描述】:

我定义了 UIDynamicAnimator 属性:

lazy fileprivate var animator: UIDynamicAnimator = 
        return UIDynamicAnimator(referenceView: self)
()

self 是 UIView 的子类;

在 self 类的扩展中,同一个文件,我有动画逻辑,使用我的动画师,添加 UIDynamicBehavior 项:

    let pushBehavior = UIPushBehavior(items: [stampView], mode: .continuous)
//some settings
    let dynamicItemBehavior = UIDynamicItemBehavior(items: [stampView])
//some settings
    let gravityBehavior = UIGravityBehavior(items: [stampView])
//some settings
    let collisionBehavior = UICollisionBehavior(items: [stampView])
//some settings

一切正常,但是当我尝试使用 removeAllBehaviors() 停止所有动画时,动画会停止,但行为仍然在 animator.behaviors 中。我第二次调用它时,数组变为空。

//======

对于我的 pushBehavior,我添加了动作,它改变了 var,表明我达到了目标点:

pushBehavior.action =  [unowned stampView] in
            if stampView.center.x <= endPosition.x 
                lastJump = true
            
        

在 collisionBehavior 委托方法中,我检查此变量并尝试使用 removeAllBehaviors() 停止动画

public func collisionBehavior(_ behavior: UICollisionBehavior, beganContactFor item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, at p: CGPoint) 
    if lastJump 
        //animator.behaviors.count = 4
        animator.removeAllBehaviors()
        //still, animator.behaviors.count = 4
    

【问题讨论】:

您显示的代码完全错误!我在您的代码中的任何地方都没有看到removeAllBehaviors。请显示那个代码,并说明你如何知道这些行为没有被删除。 @matt 现在好点了吗? 是的,现在我可以回答了。 【参考方案1】:

你说你是这样测试的:

public func collisionBehavior(_ behavior: UICollisionBehavior, beganContactFor item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, at p: CGPoint) 
    if lastJump 
        //animator.behaviors.count = 4
        animator.removeAllBehaviors()
        //still, animator.behaviors.count = 4
    

嗯,animator.removeAllBehaviors() 是一个命令,应该 删除这些行为,但不能现在执行该命令,因为这些行为仍在运行,包括你的代码就在中间的那个。如果行为真的在那一刻停止,我们甚至都不会到达你的代码的下一行!

因此,动画师在代码停止运行(也称为运行循环结束)之前实际上不会删除行为。

解决此问题的方法是等到之后您的代码停止调用removeAllBehaviors()。您可以使用我的 delay 实用程序 (https://***.com/a/24318861/341994) 轻松做到这一点:

public func collisionBehavior(_ behavior: UICollisionBehavior, beganContactFor item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, at p: CGPoint) 
    if lastJump 
        delay(0.1) 
            animator.removeAllBehaviors()
        
    

【讨论】:

感谢您的回答,但它们也不会在几秒钟后被删除。我有一些动作(让它成为按钮点击,实际上没关系),动画停止后,我按下这个按钮,行为仍然存在 好的,看我修改后的答案。但我认为还有一些你没有告诉我的事情。 是的,这就是问题所在。我正在尝试删除从行为委托属性调用的方法中的行为。所有动画都停止了,但行为似乎被保留了。谢谢!

以上是关于UIDynamicAnimator、removeAllBehaviors() 第一次不起作用的主要内容,如果未能解决你的问题,请参考以下文章

减慢 UIDynamicAnimator 的动画

如何在 applicationDidEnterBackground 中停止 UIDynamicAnimator

将 CGAffineTransformScale 与 UIAttachmentBehavior (UIDynamicAnimator) 一起使用

使用自动布局时使用 UIDynamicAnimator 制作动画

如何暂停和恢复 UIDynamicAnimator 物理模拟

第六课——UIDynamicAnimator