I have a blueView as a parent that has for own a custom constraint and this blueView has a subView called redView, the constraint of redView is always same like in the code, but the constraint of blueView is going updated after lunching app in 2 sec.
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let blueView: NSView = NSView()
blueView.wantsLayer = true
blueView.layer?.backgroundColor = NSColor.blue.cgColor
self.view.addSubview(blueView)
blueView.translatesAutoresizingMaskIntoConstraints = false
blueView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor, constant: 50.0).isActive = true
blueView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 50.0).isActive = true
blueView.widthAnchor.constraint(equalToConstant: 200.0).isActive = true
blueView.heightAnchor.constraint(equalToConstant: 200.0).isActive = true
let redView: NSView = NSView()
redView.wantsLayer = true
redView.layer?.backgroundColor = NSColor.red.cgColor
blueView.addSubview(redView)
redView.translatesAutoresizingMaskIntoConstraints = false
redView.centerXAnchor.constraint(equalTo: blueView.centerXAnchor).isActive = true
redView.centerYAnchor.constraint(equalTo: blueView.centerYAnchor).isActive = true
redView.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
redView.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(2)) {
blueView.removeConstraints(blueView.constraints)
blueView.translatesAutoresizingMaskIntoConstraints = false
blueView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
blueView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
blueView.widthAnchor.constraint(equalToConstant: 300.0).isActive = true
blueView.heightAnchor.constraint(equalToConstant: 300.0).isActive = true
}
}
}
The issue that I got is Xcode complains about Unable to simultaneously satisfy constraints:
and i think this complain is about this that I am updating my constraint in wrong way.
The second issue is that redView lose its constraint in process of updating constraint for blueView, which I want redView keeps its constraint to blueView as coded.
The third issue is that it happens without any animation, I want it happens with animation.
You're missing a couple of things. First, you don't attempt to animate anything. Second, you don't need to deactivate any constraints, you simply need to modify them.
In order to modify a constraint, you must do it on that particular constraint instance. And to do this, you may have to expand its scope by making it an instance property of the view controller, which I have done. The constraint can either be optional and nil
to start, which you can set later, or you can simply declare it on initialization and mark it lazy
, as I did here, so that it's only read when it's safe to read.
import PlaygroundSupport
import AppKit
class ViewController: NSViewController {
private let blueView = NSView()
private let redView = NSView()
private lazy var blueViewCenterXAnchor = blueView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 50)
private lazy var blueViewCenterYAnchor = blueView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 50)
private lazy var blueViewWidthAnchor = blueView.widthAnchor.constraint(equalToConstant: 200)
private lazy var blueViewHeightAnchor = blueView.heightAnchor.constraint(equalToConstant: 200)
override func loadView() {
view = NSView()
}
override func viewDidLoad() {
super.viewDidLoad()
blueView.wantsLayer = true
blueView.layer?.backgroundColor = NSColor.blue.cgColor
blueView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(blueView)
blueViewCenterXAnchor.isActive = true
blueViewCenterYAnchor.isActive = true
blueViewWidthAnchor.isActive = true
blueViewHeightAnchor.isActive = true
redView.wantsLayer = true
redView.layer?.backgroundColor = NSColor.red.cgColor
redView.translatesAutoresizingMaskIntoConstraints = false
blueView.addSubview(redView)
redView.centerXAnchor.constraint(equalTo: blueView.centerXAnchor).isActive = true
redView.centerYAnchor.constraint(equalTo: blueView.centerYAnchor).isActive = true
redView.widthAnchor.constraint(equalToConstant: 100).isActive = true
redView.heightAnchor.constraint(equalToConstant: 100).isActive = true
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(2)) {
self.blueViewCenterXAnchor.constant = 0
self.blueViewCenterYAnchor.constant = 0
self.blueViewWidthAnchor.constant = 300
self.blueViewHeightAnchor.constant = 300
NSAnimationContext.runAnimationGroup { context in
context.allowsImplicitAnimation = true
context.duration = 3
self.view.layoutSubtreeIfNeeded()
}
}
}
}
PlaygroundPage.current.liveView = ViewController()