translatesAutoresizingMaskIntoConstraints = true, so UIKit converts its frame into required constraints that fight the ones you add. Set it to false before adding anything, and replace your width and height constraints — width == width with constant 0 defines nothing — with constant constraints or anchor constraints.Why this happens
UIView(frame:) gives the view a frame, and a view created in code defaults to translatesAutoresizingMaskIntoConstraints = true. That flag tells UIKit to convert the frame into a set of required layout constraints — the NSAutoresizingMaskLayoutConstraint lines in your log, the ones with h=--& v=--& and values like midX == + 50.
Those generated constraints are required. When you then add centerX == view.centerX on top of them, Auto Layout has two independent required position/size sources and drops one of your constraints with Unable to simultaneously satisfy constraints. The log even names the victim in the Will attempt to recover by breaking constraint line.
The second problem is separate but related: your width and height constraints are written as newView.width == newView.width with constant 0. That is a tautology — it holds for any width — so it never pins the size to 100. Once the autoresizing mask is gone, the view would have no intrinsic size and would collapse or stretch.
How to fix it
1. Turn off the autoresizing mask translation
This is the fix for the log itself. Set the flag before adding constraints, so the frame is no longer exported as constraints:
let newView = UIView()
newView.backgroundColor = .systemRed
newView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(newView)
Notice that the frame is gone too. Once the flag is false, the frame is an output of Auto Layout, not an input, so UIView(frame:) buys you nothing. Create the view with UIView() and let the constraints decide its geometry.
2. Give the view an actual size
A constant size constraint must not point at the view itself. In the older initializer form, pass nil and .notAnAttribute:
let width = NSLayoutConstraint(item: newView, attribute: .width,
relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute,
multiplier: 1, constant: 100)
let height = NSLayoutConstraint(item: newView, attribute: .height,
relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute,
multiplier: 1, constant: 100)
With anchors it is simply equalToConstant:
newView.widthAnchor.constraint(equalToConstant: 100)
newView.heightAnchor.constraint(equalToConstant: 100)
3. Switch to the anchor API and activate the constraints
The full working version of the original snippet, centered and 100×100:
override func viewDidLoad() {
super.viewDidLoad()
let newView = UIView()
newView.backgroundColor = .systemRed
newView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(newView)
NSLayoutConstraint.activate([
newView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
newView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
newView.widthAnchor.constraint(equalToConstant: 100),
newView.heightAnchor.constraint(equalToConstant: 100)
])
}
The equivalent without anchors, if you are maintaining older code:
newView.translatesAutoresizingMaskIntoConstraints = false
let centerX = NSLayoutConstraint(item: newView, attribute: .centerX, relatedBy: .equal,
toItem: view, attribute: .centerX,
multiplier: 1, constant: 0)
let centerY = NSLayoutConstraint(item: newView, attribute: .centerY, relatedBy: .equal,
toItem: view, attribute: .centerY,
multiplier: 1, constant: 0)
let width = NSLayoutConstraint(item: newView, attribute: .width, relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute,
multiplier: 1, constant: 100)
let height = NSLayoutConstraint(item: newView, attribute: .height, relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute,
multiplier: 1, constant: 100)
NSLayoutConstraint.activate([centerX, centerY, width, height])
NSLayoutConstraint.activate(_:) adds each constraint to the correct view for you. If you prefer the older style, constraint.isActive = true does the same thing one at a time.
4. Attach constraints to the right view
view.addConstraint(...) requires the receiving view to be the nearest common ancestor of the items in the constraint. A width constraint on newView only involves newView, so it belongs on newView, not on self.view. Adding it to the controller’s view can produce confusing behavior or the Unable to activate constraint with anchors ... because they have no common ancestor exception when using anchors. Use activate and avoid the question entirely.
5. Debug what is left with a symbolic breakpoint
The log already tells you what to do: add a symbolic breakpoint on UIViewAlertForUnsatisfiableConstraints (Breakpoint Navigator → + → Symbolic Breakpoint). It pauses at the exact moment the conflict is detected, so you can inspect which view and which constraints are involved instead of guessing from the printed list.
If the conflict is intentional — a layout that should give way at some size — do not remove the constraint; lower its priority:
let width = newView.widthAnchor.constraint(equalToConstant: 100)
width.priority = .defaultHigh
width.isActive = true
How to prevent it
- Set
translatesAutoresizingMaskIntoConstraints = falseimmediately after creating any view you lay out in code. - Do not mix
frameand constraints for the same view; pick one and stay with it. - Write size constraints as
equalToConstantor withtoItem: nil, attribute: .notAnAttribute, never as a self-reference with constant 0. - Prefer
NSLayoutConstraint.activate([...])over individualaddConstraintcalls so constraints land on the right view. - Keep the
UIViewAlertForUnsatisfiableConstraintssymbolic breakpoint in your project while developing layouts.
FAQ
Why does the log mention NSAutoresizingMaskLayoutConstraints I never created?
Because the view’s translatesAutoresizingMaskIntoConstraints is still true, so UIKit generated them from its frame. They disappear as soon as you set the flag to false.
Does setting frame still do anything after I use Auto Layout?
No. With the translation flag off, frame is recalculated at layout time from the constraints, so any value you assign earlier is overwritten.
Why is width == width with constant 0 not a valid width constraint?
It compares the view’s width to itself, which is always true and constrains nothing. A constant size needs no second item, which is why the initializer takes nil and .notAnAttribute.
Parts of this guide are adapted from content licensed under CC BY-SA 4.0; this article is shared under the same license.
