Swift - 不被调用的UICollisionBehavior委托方法
我正在做一个简单的动画,它需要我处理边界的碰撞。Swift - 不被调用的UICollisionBehavior委托方法
我有一个类,viewcontroller,我扩展为一个UICollisionBehaviorDelegate,所以我可以识别并处理视图冲突。
由于某些原因,当碰撞发生时,我的委托方法从不触发。
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)
}
}
我完全废弃了旧的答案并更新了它。对不起,我误导了你,但这里是我修改后的答案:
这个想法是你想要动画的对象添加行为(在你的情况下,你的fallingImageViews
)。
所以这里的所有代码实际上应该进入从UIImageView继承的类(在我的示例代码中,您将看到我从CardCtrl对象继承,但它可能也是UIImageView)。
您必须做出的唯一更改是您的UIDynamicAnimator
的参考视图必须是superview
,并且所有动画行为的所有参考视图都设置为[self]
。
这里是我的老项目之一一些示例代码:
@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)
}
}
}
尝试改变线let downAnimator = initializeAnimators()
在viewDidLoad()
到downAnimator = initializeAnimators()
对不起,这是发布的代码示例中的一个错字,而不是我自己的。 – Beezebrown
眼下,边界正在正确应用 - 即,在元素fallingimageViews与参考范围相冲突。 我试图解决的问题是,当这个碰撞发生时,'collisionBehaviorBeganContactFor方法'不会被触发。 – Beezebrown
您的委托不会触发,因为您的视图控制器符合UICollisionBehaviorDelegate,而不是您的fallingImageViews。 如果您将collisionDelegate分配给self,那么您的视图控制器将成为碰撞的观察者,但在您的情况下,您的视图控制器没有碰撞边界,那么应该如何检测碰撞? (对不起,在我完全输入我的答案之前,我不小心输入了过早) –
你试过我的建议吗? (将'items:fallingImageViews'改为'items:[self.view]') –