constraints priority
runtime changes
dynamic constraints
priority adjustment
programming tips

How can I change constraints priority in run time

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Auto Layout, constraint priority is what tells the layout engine which rules are negotiable when not every constraint can be satisfied at once. Changing that priority at runtime is a normal technique for adapting a view hierarchy to state changes, animations, content size changes, or orientation changes.

The key point is that you usually do not destroy and recreate every constraint. In UIKit and AppKit, you can often keep a reference to the existing constraint and update its priority property directly.

How Constraint Priority Works

Constraint priorities range from 1 to 1000. A priority of 1000 means required, while lower values give Auto Layout flexibility to break that constraint if needed.

This allows patterns such as:

  • one layout constraint active at high priority in compact space
  • another preferred in expanded space
  • both present, but the higher-priority one wins

At runtime, changing priority is often cleaner than repeatedly activating and deactivating competing constraints.

Changing Priority in Code

The usual approach is:

  1. keep a stored reference to the constraint
  2. update its priority when state changes
  3. trigger layout updates

Here is a simple UIKit example in Swift:

swift
1import UIKit
2
3final class ProfileViewController: UIViewController {
4    @IBOutlet private weak var compactTopConstraint: NSLayoutConstraint!
5    @IBOutlet private weak var expandedTopConstraint: NSLayoutConstraint!
6
7    override func viewDidLoad() {
8        super.viewDidLoad()
9        applyExpandedLayout(false)
10    }
11
12    @IBAction private func toggleLayout(_ sender: UISwitch) {
13        applyExpandedLayout(sender.isOn)
14    }
15
16    private func applyExpandedLayout(_ expanded: Bool) {
17        if expanded {
18            compactTopConstraint.priority = .defaultLow
19            expandedTopConstraint.priority = .required - 1
20        } else {
21            compactTopConstraint.priority = .required - 1
22            expandedTopConstraint.priority = .defaultLow
23        }
24
25        UIView.animate(withDuration: 0.25) {
26            self.view.layoutIfNeeded()
27        }
28    }
29}

Using .required - 1 instead of a hard 1000 for a strong preference is a common practical technique. It leaves room for the system to resolve edge cases without generating unsatisfiable-constraint warnings.

Interface Builder and Outlets

If the constraints are created in Interface Builder, connect them as outlets. That makes runtime changes easy and keeps the layout definition readable in the storyboard or XIB.

If the constraints are created in code, store them in properties when you activate them:

swift
1titleLabel.translatesAutoresizingMaskIntoConstraints = false
2
3let centered = titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor)
4centered.priority = .defaultHigh
5centered.isActive = true

Once you have the reference, changing centered.priority later is enough.

Priority Changes Versus Activation Changes

Changing priority and toggling activation are related but different tools.

Use priority changes when:

  • both constraints conceptually exist all the time
  • one should dominate depending on state
  • you want smoother animated transitions

Use activation changes when:

  • a constraint should truly not participate in layout
  • the layout rules are mutually exclusive
  • keeping both constraints around creates ambiguity

In practice, many interfaces use a mix of both techniques.

Animating Layout Changes

Runtime priority updates are especially useful for animation. After adjusting priorities, call layoutIfNeeded() inside an animation block so Auto Layout interpolates the frame changes.

swift
1UIView.animate(withDuration: 0.3) {
2    self.compactTopConstraint.priority = .defaultLow
3    self.expandedTopConstraint.priority = .required - 1
4    self.view.layoutIfNeeded()
5}

This produces a cleaner result than manually changing frames in most constraint-based interfaces.

Common Pitfalls

The biggest pitfall is changing priorities on constraints that still leave the layout ambiguous. Auto Layout needs a complete enough rule set to determine frames after the change.

Another issue is relying too heavily on priority 1000. Two conflicting required constraints cannot both win, so the engine will break one and log warnings. Often a priority of 999 is the safer expression of a very strong preference.

It is also easy to forget to call layoutIfNeeded() after a runtime update, especially when animating. Without it, the constraint change may not appear when you expect.

Finally, make sure you are modifying the correct constraint reference. In complex layouts, several similar constraints may exist, and changing the wrong one can make debugging look random.

Summary

  • You can change Auto Layout constraint priority at runtime by updating the constraint’s priority property.
  • Store a reference to the constraint, usually through an outlet or a property created in code.
  • Priority changes are useful when multiple constraints may exist but one should win depending on state.
  • Use layoutIfNeeded() to apply and animate the resulting layout update.
  • Prefer near-required priorities such as 999 when you want strong preference without rigid conflicts.

Course illustration
Course illustration

All Rights Reserved.