I'm creating a gesture on a view that I called separatorView (in the photo it's the middle black view).
I use the constraint method and the priorities to do it:
-centerConstraint = This is the constraint that allows to center the view horizontally in X, priority = 1000
-rightConstant = This constraint links the view to the edge of the right screen at zero pt, priority = 999
-GaucheConstant = This constraint links the view to the edge of the left screen at zero pt, priority = 998
When I drag this view to the left, the animation continues to drag.
The problem is that after the animation is finished, and I want to resume the view and drag it to the left the cash application centerConstraint is nil!
I can not find the solution to make it all generic and I can slide the view to the right or left without any problem
I know the problem comes from the fact that I disable the constraint
here my code:
@IBOutlet weak var sep: UIView!
@IBOutlet weak var constantGauche: NSLayoutConstraint!
@IBOutlet weak var constantDroite: NSLayoutConstraint!
@IBOutlet weak var centerConstraint: NSLayoutConstraint!
var startingConstant: CGFloat = 0.0
var panGesture: UIPanGestureRecognizer?
override func viewDidLoad() {
super.viewDidLoad()
panGesture = UIPanGestureRecognizer(target: self, action: #selector(detectPan(recognizer:)))
panGesture?.delaysTouchesBegan = false
panGesture?.delaysTouchesEnded = false
sep.addGestureRecognizer(panGesture!)
}
@objc func detectPan(recognizer: UIPanGestureRecognizer) {
let translation = recognizer.translation(in: self.view)
switch recognizer.state {
case .began:
self.startingConstant = self.centerConstraint.constant
case .changed:
self.centerConstraint.constant = self.startingConstant + translation.x
case .ended:
if translation.x > 0 {
centerConstraint.isActive = false
constantGauche.isActive = false
constantDroite.isActive = true
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
}else{
centerConstraint.isActive = false
constantGauche.isActive = true
constantDroite.isActive = false
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
}
default:
break
}
}
Yes, when you disable the center constraint, iOS removes it from the view's constraints and frees it because there is no longer a strong reference to it. The @IBOutlet
is a weak
reference which gets set to nil
as soon as the strong references are all gone. So the next time you access the center constraint, it crashes because it is nil
and centerConstraint
is implicitly unwrapped with !
.
Instead of disabling constraints, modify their priorities:
999
as a starting value. You'll get an error if you try to modify a required constraint's priority in code.priority
of the left and center constraints will cause sep
to move to the right. Once it gets there, you can calculate the new constant
for the center constraint and then set their priorities back to the starting values.priority
of the right and center constraints will cause sep
to move to the left. Once it gets there, you can calculate the new constant
for the center constraint and then set their priorities back to the starting values.@objc func detectPan(recognizer: UIPanGestureRecognizer) {
let translation = recognizer.translation(in: self.view)
switch recognizer.state {
case .began:
self.startingConstant = self.centerConstraint.constant
case .changed:
self.centerConstraint.constant = self.startingConstant + translation.x
case .ended:
if translation.x > 0 {
centerConstraint.priority = UILayoutPriority(rawValue: 750)
constantGauche.priority = UILayoutPriority(rawValue: 750)
} else {
centerConstraint.priority = UILayoutPriority(rawValue: 750)
constantDroite.priority = UILayoutPriority(rawValue: 750)
}
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
print(sep.center.x - view.center.x)
centerConstraint.constant = sep.center.x - view.center.x
centerConstraint.priority = UILayoutPriority(rawValue: 999)
constantGauche.priority = UILayoutPriority(rawValue: 998)
constantDroite.priority = UILayoutPriority(rawValue: 998)
default:
break
}
}
Here are the changes running in the simulator: