My app has a custom UIButton with two subviews that look like they're hanging by strings. When the user taps the button, one gets pulled back, then collides with the other. This is working for me on the first collision, but when I go to tap a second time, the item doesn't get pulled back.
On the first call to layoutSubviews()
, I add both views to a UIGravityBehavior
, and I give them each their own UIAttachmentBehavior
. On touchesBegan
, I add a collision adjacent to the view that needs to get pulled back, and then either on touchesEnded
or after a timer if it was a tap and not a long press, I remove the collision that was holding it in place.
I store that collision in an instance variable (so it's retained), and create it like so:
holdCollision = UICollisionBehavior(items: [theView])
holdCollision.addBoundaryWithIdentifier("boundary suspending item in air",
forPath: UIBezierPath(rect: holdCollisionViewFrame))
If I construct the UICollisionBehavior
once and then call addBehavior
and removeBehavior
with it multiple times, it only works the first time. If I construct it from scratch on each tap, it always works. What could be causing this?
Update: I came up with a sample project for reporting to Apple. You can reproduce in a clean single-view iOS project. Add two views, one over the other, and link to the outlets at the top. The top view needs to be large enough that it overlaps with the bottom one at first launch, or you wont' see the problem. Add two buttons and connect to the actions at the bottom.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var topView: UIImageView!
@IBOutlet weak var bottomView: UIView!
var animator: UIDynamicAnimator!
var collision: UICollisionBehavior!
override func viewDidLoad() {
super.viewDidLoad()
animator = UIDynamicAnimator(referenceView: view)
let gravity = UIGravityBehavior(items: [topView])
animator.addBehavior(gravity)
var anchor = view.center
anchor.y -= 100
let attachment = UIAttachmentBehavior(item: topView, attachedToAnchor: anchor)
animator.addBehavior(attachment)
collision = UICollisionBehavior(items: [topView])
collision.addBoundaryWithIdentifier("bottom boundary", forPath: UIBezierPath(rect: bottomView.frame))
}
@IBAction func addCollision() {
NSLog("boundaries: \(collision.boundaryIdentifiers)")
animator.addBehavior(collision)
}
@IBAction func removeCollision() {
animator.removeBehavior(collision)
}
}