Методы UICollisionBehaviorDelegate не вызваны
Я работал над приложением и реализовал обнаружение столкновений, используя UIKitDynamics.
Обнаружение столкновения работает. Но почему-то методы UICollisionBehaviorDelegate не вызываются. Предупреждения или ошибки не отображаются.
Я создал пример проекта, чтобы продемонстрировать проблему:
import UIKit
class ViewController: UIViewController {
private var dynamicAnimator: UIDynamicAnimator?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.initPhysics()
}
fileprivate var initalized = false
fileprivate func initPhysics() {
if initalized {
return
}
initalized = true
let physicsView = UIView(frame: view.bounds.insetBy(dx: 40, dy: 40))
physicsView.backgroundColor = UIColor.black
self.dynamicAnimator = UIDynamicAnimator(referenceView: physicsView)
physicsView.isUserInteractionEnabled = false
view.addSubview(physicsView)
//Create ball
let frame = CGRect(x: 0, y: 0, width: 40, height: 40)
let rect = UIView(frame: frame)
rect.backgroundColor = UIColor.red
physicsView.addSubview(rect)
let behavior = UIDynamicItemBehavior(items: [rect])
behavior.elasticity = 1.0
behavior.resistance = 0.0
behavior.friction = 0.0
behavior.allowsRotation = false
self.dynamicAnimator?.addBehavior(behavior)
//collision behavior setup
let collisionBehavior = UICollisionBehavior(items: [rect])
collisionBehavior.collisionDelegate = self
collisionBehavior.setTranslatesReferenceBoundsIntoBoundary(with: .zero)
collisionBehavior.collisionMode = .everything
self.dynamicAnimator?.addBehavior(collisionBehavior)
//Push ball
let pushBehavior = UIPushBehavior(items: [rect], mode: UIPushBehaviorMode.instantaneous)
pushBehavior.active = true
pushBehavior.pushDirection = CGVector(dx: 0.5, dy: 0.5)
self.dynamicAnimator?.addBehavior(pushBehavior)
}
}
extension ViewController: UICollisionBehaviorDelegate {
// DELEGATE METHODS NOT CALLED
func collisionBehavior(_ behavior: UICollisionBehavior,
beganContactFor item: UIDynamicItem,
withBoundaryIdentifier identifier: NSCopying?,
at p: CGPoint) {
print("began contact boundary")
}
func collisionBehavior(_ behavior: UICollisionBehavior,
endedContactFor item: UIDynamicItem,
withBoundaryIdentifier identifier: NSCopying?) {
print("contact boundary ended")
}
func collisionBehavior(_ behavior: UICollisionBehavior,
endedContactFor item1: UIDynamicItem,
with item2: UIDynamicItem) {
print("contact item ended")
}
func collisionBehavior(_ behavior: UICollisionBehavior,
beganContactFor item1: UIDynamicItem,
with item2: UIDynamicItem,
at p: CGPoint) {
print("began contact item")
}
}
Базовый SDK: iOS 11.2, Xcode Version 9.2 (9C40b)
Спасибо за помощь!
1 ответ
Это не то, как это работает (к сожалению).. У вас есть только один элемент в вашем поведении столкновения, и вы просите его обнаружить столкновение с чем??? Если вы добавили второй элемент, вы увидите, что делегат вызван..
Реальный вопрос почему? Ну, столкновение обнаруживает, пересекается ли кадр одного элемента с кадром другого.. Если он сделал то, что вы просите (rect
это ребенок physicsView
), тогда он ВСЕГДА будет сталкиваться (это не то, что вы хотите)..
Так как ваш physicsView
не является частью поведения при столкновении, вы ничего не получаете.. Вы сказали ему ограничить элемент в его пределах (setTranslatesReferenceBoundsIntoBoundary
работает над элементами, добавленными к самому поведению), но не для обнаружения столкновения с границами. Например, если элемент находился вне physicsView
, он не сможет войти. Если он внутри, он не может выйти. Но это не будет считаться столкновением за слово (иначе это всегда столкновение).
Для того, чтобы обнаружить столкновение между вашим rect
и ваш physicsView
нужно дать physicsView
некоторые физические свойства.. Сейчас это просто обычный UIView
(справочный вид)..
Другой способ обойти физические свойства - добавить для него границу:
collisionBehavior.addBoundary(withIdentifier: "PhysicsViewBoundary" as NSString, for: UIBezierPath(rect: physicsView.bounds))
Теперь он позвонит:
func collisionBehavior(_ behavior: UICollisionBehavior,
beganContactFor item: UIDynamicItem,
withBoundaryIdentifier identifier: NSCopying?,
at p: CGPoint) {
print("began contact boundary")
}
func collisionBehavior(_ behavior: UICollisionBehavior,
endedContactFor item: UIDynamicItem,
withBoundaryIdentifier identifier: NSCopying?) {
print("contact boundary ended")
}