swift - Swift:启用或禁用约束错误
问题描述
我正在一个名为 separatorView 的视图上创建一个手势(在照片中它是中间的黑色视图)。
我使用约束方法和优先级来做到这一点:
-centerConstraint = 这是允许在 X 中水平居中视图的约束,优先级 = 1000
-rightConstant = 此约束将视图链接到右屏幕边缘的零点,优先级 = 999
-GaucheConstant = 此约束将视图链接到左屏幕边缘的零点,优先级 = 998
当我将此视图拖到左侧时,动画会继续拖动。
问题是动画完成后,我想恢复视图并将其拖到左侧现金应用程序中心约束为nil!
我找不到使其通用的解决方案,我可以将视图向右或向左滑动而没有任何问题
我知道问题出在我禁用约束的事实
这是我的代码:
@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
}
}
解决方案
是的,当您禁用中心约束时,iOS 会将其从视图的约束中移除并释放它,因为不再有对它的强引用。这@IBOutlet
是一个引用,一旦强引用全部消失,weak
它就会被设置为。nil
因此,下次您访问中心约束时,它会崩溃,因为它已经并且nil
隐含地用.centerConstraint
!
不要禁用约束,而是修改它们的优先级:
- 将中心约束优先级更改为
999
作为起始值。如果您尝试在代码中修改所需约束的优先级,则会收到错误消息。 - 降低
priority
左侧和中心约束的 将导致sep
向右移动。一旦它到达那里,您可以计算中心constant
约束的新值,然后将它们的优先级设置回起始值。 - 降低
priority
右侧和中心约束的 将导致sep
向左移动。一旦它到达那里,您可以计算中心constant
约束的新值,然后将它们的优先级设置回起始值。
@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
}
}
以下是模拟器中运行的更改:
推荐阅读
- wordpress - 第一次尝试登录的访问者总是显示 cookie 错误
- android - 对话框弹出很慢
- numpy-ndarray - 从python中的数据集中过滤索引
- html - Bootstrap模态滚动条在触发另一个模态后出现和消失
- authentication - istio 得到“RBAC:访问被拒绝”,即使服务角色绑定被检查为允许
- android - 测试用例在 Firebase 测试实验室失败,但在本地机器上工作
- docker - 如何从 dockerised ELK 中清除日志文件?
- jwt - 如何从 JWKSet 文件中签署 JWT?
- ios - 如何减少 Xcode 链接时间?
- python-3.x - 如何使用 sklearn 计算 Precision、Recall 和 F1 分数