简体   繁体   English

Swift - UICollisionBehavior 委托方法未被调用

[英]Swift - UICollisionBehavior delegate methods not being called

I'm doing a simple animation which requires me to handle some collisions with boundaries.我正在做一个简单的动画,它需要我处理一些与边界的碰撞。

I have a class, viewcontroller, which I extend to be a UICollisionBehaviorDelegate so I can recognize and handle view collisions.我有一个类,viewcontroller,我将它扩展为 UICollisionBehaviorDelegate,这样我就可以识别和处理视图冲突。

For some reason, when a collision happens, my delegate methods never fire.出于某种原因,当发生碰撞时,我的委托方法永远不会触发。

class ViewController: UIViewController {

    var fallingImageViews: [UIImageView]!
    var downAnimator: UIDynamicAnimator!

    override func viewDidLoad() {
        super.viewDidLoad()

        //imagine fallingImageViews Initializers happening here

        downAnimator = initializeAnimators()
    }

    func initializeAnimators() -> UIDynamicAnimator {
        let downwardAnimator = UIDynamicAnimator(referenceView: self.view)

        downwardAnimator.addBehavior(setBoundaries())
        downwardAnimator.addBehavior(setGravity())
        downwardAnimator.addBehavior(setBounciness())
        downwardAnimator.delegate = self

        return downwardAnimator
    }

    func setBoundaries() -> UICollisionBehavior {
        let boundaries = UICollisionBehavior(items: fallingImageViews)
        boundaries.collisionDelegate = self

        // prevent collisions between items
        boundaries.collisionMode = .boundaries

        boundaries.setTranslatesReferenceBoundsIntoBoundary = true

        return boundaries
    }
}

// MARK: Collision Behavior Delegate
extension ViewController: UICollisionBehaviorDelegate, UIDynamicAnimatorDelegate {

    func collisionBehavior(_ behavior: UICollisionBehavior, endedContactFor item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?) {
        print(identifier)
    }
    func collisionBehavior(_ behavior: UICollisionBehavior, beganContactFor item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, at p: CGPoint) {
        print(identifier)
    }
}

I completely scrapped my old answer and updated it.我完全废弃了我的旧答案并更新了它。 I'm sorry I mislead you, but here is my revised answer:对不起,我误导了你,但这是我修改后的答案:

The idea is that you add behaviors to the objects you want animated (in your case, your fallingImageViews ).这个想法是你向你想要动画的对象添加行为(在你的情况下,你的fallingImageViews )。

So all the code here should actually go into a class that inherits from UIImageView (in my example code you'll see that I'm inheriting from a CardCtrl object, but it might as well be a UIImageView).所以这里的所有代码实际上应该进入一个继承自 UIImageView 的类(在我的示例代码中,您将看到我继承自 CardCtrl 对象,但它也可能是一个 UIImageView)。

The only changes you have to make is your UIDynamicAnimator 's reference view has to be superview and that all the the reference views for all your animation behaviors are set to [self] .您唯一需要做的更改是UIDynamicAnimator的参考视图必须是UIDynamicAnimator superview ,并且所有动画行为的所有参考视图都设置为[self]

Here is some example code from one of my old projects:这是我的一个旧项目中的一些示例代码:

@IBDesignable class SlidingCard: CardCtrl, UICollisionBehaviorDelegate
{
   ...
    //MARK: - Private Properties

    private var gripHeightAnch: NSLayoutConstraint = NSLayoutConstraint()
    private var animator: UIDynamicAnimator!
    private var dynamicItem: UIDynamicItemBehavior!
    private var collisionBnds: UICollisionBehavior!
    private var snap: UISnapBehavior!
    private var botBndryPt: CGFloat!
    private var gravity: UIGravityBehavior!
    private var pan: UIPanGestureRecognizer!

    ...

    //MARK: - Delegate Methods

    func collisionBehavior(_ behavior: UICollisionBehavior, beganContactFor item: UIDynamicItem,
                           withBoundaryIdentifier identifier: NSCopying?, at p: CGPoint)
    {
        guard let identifier = identifier else {return}
        if String(describing: identifier) == "bot"
        {
            sendActions(for: .touchDragOutside)
        }
        else
        {
            sendActions(for: .touchDragInside)
        }
    }

    ...

    //MARK: - Private Setup Methods

    private func defineSlideBehavior()
    {
        if animator == nil
        {
            animator = UIDynamicAnimator(referenceView: superview!)
        }
        animator!.removeAllBehaviors()

        //Check to see if behaviors are already installed because .removeAllBehaviors() doesn't
        //always work
        var addItem = true
        var addBounds = true
        var addGravity = true
        for blarHar in animator!.behaviors
        {
            if blarHar.isKind(of: UIDynamicItem.self)
            {
                addItem = false
            }
            if blarHar.isKind(of: UICollisionBehavior.self)
            {
                addBounds = false
            }
            if blarHar.isKind(of: UIGravityBehavior.self)
            {
                addGravity = false
            }
        }
        //Make it so the card doesn't wobble
        if dynamicItem == nil && addItem
        {
            dynamicItem = UIDynamicItemBehavior(items: [self])
            dynamicItem.allowsRotation = false
            dynamicItem.elasticity = 0
        }
        animator!.addBehavior(dynamicItem)

        //Add two boundaries for the drawer to collide with
        if collisionBnds == nil && addBounds
        {
            collisionBnds = UICollisionBehavior(items: [self])
            collisionBnds.collisionDelegate = self
        }
        botBndryPt = frame.maxY * 2 + 1.5
        collisionBnds.removeAllBoundaries()
        collisionBnds.addBoundary(withIdentifier: "top" as NSCopying,
                                  from: CGPoint(x: frame.minX, y: frame.minY - 1.5),
                                  to: CGPoint(x: frame.maxX, y: frame.minY - 1.5))
        collisionBnds.addBoundary(withIdentifier: "bot" as NSCopying,
                                  from: CGPoint(x: frame.minX, y: botBndryPt),
                                  to: CGPoint(x: frame.maxX, y: botBndryPt))
        animator!.addBehavior(collisionBnds)

        //Define the initial gravity that affects the drawer
        if addGravity
        {
            gravity = UIGravityBehavior(items: [self])
            gravity.gravityDirection = CGVector(dx: 0, dy: -gravityStrength)
            animator!.addBehavior(gravity)
        }
    }
}

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

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