Reputation: 179
I am trying to toggle between two programmable view constraints, depending on the orientation of the device.
To toggle I set the old height/width constraints to isActive=False
in viewWillLayoutSubviews()
and the new constraints to isActive=True
in viewDiDLayoutSubViews()
, however I get an
“unable to simultaneously satisfy constraints”
error in the debug, and it blocks the newConstraints.
Any advice on where to block the old constraints?
The IBOutlet
for my View is set to ‘Strong’
. I have also tried applying .layoutIfNeeded
after changing the old constraint to isActive=False
, but it still seems to be active.
Please see pertinent code below. The layout works well initially however after device rotation the new constraints in the updateViewLayouts method get blocked. I believe the new constraints are correct, I just need to disable the old constraints at the correct time.
override func viewWillLayoutSubviews() {
super.viewDidLayoutSubviews()
if view.orientationHasChanged(&isInPortrait) {
orientationWillChange()
}
if isInPortrait { //Disable Landscape constraints
imageView1.heightAnchor.constraint(equalTo: frameView.heightAnchor, multiplier: 1.0).isActive = false
imageView1.widthAnchor.constraint(equalTo: frameView.widthAnchor, multiplier: 0.5).isActive = false
} else { //Disable Portrait constraints
imageView1.heightAnchor.constraint(equalTo: frameView.heightAnchor, multiplier: 0.5).isActive = false
imageView1.widthAnchor.constraint(equalTo: frameView.widthAnchor, multiplier: 1.0).isActive = false
}
imageView1.layoutIfNeeded()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if orientationDidChange {
updateViewLayouts()
orientationDidChange = false
}
}
func updateViewLayouts() {
imageView1.topAnchor.constraint(equalTo: frameView.topAnchor).isActive = true
imageView1.leadingAnchor.constraint(equalTo: frameView.leadingAnchor).isActive = true
if isInPortrait {
imageView1.heightAnchor.constraint(equalTo: frameView.heightAnchor, multiplier: 0.5).isActive = true
imageView1.widthAnchor.constraint(equalTo: frameView.widthAnchor, multiplier: 1.0).isActive = true
} else { //LANDSCAPE
imageView1.heightAnchor.constraint(equalTo: frameView.heightAnchor, multiplier: 1.0).isActive = true
imageView1.widthAnchor.constraint(equalTo: frameView.widthAnchor, multiplier: 0.5).isActive = true
}
}
Upvotes: 1
Views: 77
Reputation: 119666
This is not how it works
imageView1.heightAnchor.constraint(equalTo: frameView.heightAnchor, multiplier: 1.0).isActive = false
Because every time you call .constraint(...
, it creates new constraint and return it back to you. So setting it to false is none sense because it's will create and destroy at the same time.
For disabling that, you need to take a reference to the constraint, and deactivate that later:
//Persistant variable
var portraitHeightConstraint: NSLayoutConstraint?
// If portrait
portraitHeightConstraint = imageView1.heightAnchor.constraint(equalTo: frameView.heightAnchor, multiplier: 1.0)
portraitHeightConstraint?.isActive = true
// And later if needed
portraitHeightConstraint?.isActive = false
// And same logic for horizontal and other constraints
Please note that I write this without compiler and may have some syntax errors. Don't panic.
Upvotes: 1