Autolayout with Anchors in swift

  1. Using Auto Layout Visual Format Language.
  2. Using Layout Anchors.

Steps need to follow to add constraints:-

  • Call addSubview so that view is in the hierarchy.
  • Set translatesAutoresizingMaskIntoConstraints = false
  • Create constraints and set isActive = true to enable constraints.
  • When activating or deactivating lots of constraints at once, it’s more efficient to pass them as an array to activate() and deactivate() respectively.
  1. Create a view with background colour
let redView = UIView()
redView.backgroundColor = UIColor.red
redView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(redView)
redView.widthAnchor.constraint(equalToConstant: 100).isActive = true
redView.heightAnchor.constraint(equalToConstant: 100).isActive = true
NSLayoutConstraint.activate([
redView.widthAnchor.constraint(equalToConstant: 100),
redView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
redView.heightAnchor.constraint(equalTo: redView.widthAnchor, multiplier: 1),
redView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])

API’s available for setting Constraints:-

The cool thing about NSLayoutAnchor is its generic constrained API design. Constraints are divided into X-axis, Y-axis and dimension anchor type that makes it hard to make mistakes.

open class NSLayoutXAxisAnchor : NSLayoutAnchor<NSLayoutXAxisAnchor>
open class NSLayoutDimension : NSLayoutAnchor<NSLayoutDimension>
open class NSLayoutYAxisAnchor : NSLayoutAnchor<NSLayoutYAxisAnchor>
  1. Use bellow methods for setting system spacing between to views
// for y axis
1. constraint(equalToSystemSpacingBelow anchor: NSLayoutYAxisAnchor, multiplier: CGFloat) -> NSLayoutConstraint
2. constraint(greaterThanOrEqualToSystemSpacingBelow anchor: NSLayoutYAxisAnchor, multiplier: CGFloat) -> NSLayoutConstraint
3. constraint(lessThanOrEqualToSystemSpacingBelow anchor: NSLayoutYAxisAnchor, multiplier: CGFloat) -> NSLayoutConstraint
// for x axis
4. constraint(equalToSystemSpacingAfter anchor: NSLayoutXAxisAnchor, multiplier: CGFloat) -> NSLayoutConstraint5. constraint(greaterThanOrEqualToSystemSpacingAfter anchor: NSLayoutXAxisAnchor, multiplier: CGFloat) -> NSLayoutConstraint6. constraint(lessThanOrEqualToSystemSpacingAfter anchor: NSLayoutXAxisAnchor, multiplier: CGFloat) -> NSLayoutConstraint
//for width and hight
1. constraint(equalTo anchor: NSLayoutDimension, multiplier m: CGFloat, constant c: CGFloat) -> NSLayoutConstraint
2. constraint(greaterThanOrEqualTo anchor: NSLayoutDimension, multiplier m: CGFloat, constant c: CGFloat) -> NSLayoutConstraint
3. constraint(lessThanOrEqualTo anchor: NSLayoutDimension, multiplier m: CGFloat, constant c: CGFloat) -> NSLayoutConstraint
// for x and y axis
4. constraint(equalTo anchor: NSLayoutAnchor<AnchorType>) -> NSLayoutConstraint
5. constraint(greaterThanOrEqualTo anchor: NSLayoutAnchor<AnchorType>) -> NSLayoutConstraint
6. constraint(lessThanOrEqualTo anchor: NSLayoutAnchor<AnchorType>) -> NSLayoutConstraint

How can you set priority for constraints?

You can set priority for any constraint using UILayoutPriority of range 1 to 1000. Click here to know about autolayout fundamental and view priority

// added priority for width constraint
let
widthConstrain = redView.widthAnchor.constraint(equalToConstant: 100)
widthConstrain.priority = UILayoutPriority(rawValue: 999)
widthConstrain.isActive = true

What is aspect ratio and How can you set this?

  • Aspect ratio describes the ratio between the width and height of a view or screen.
  • A 1:1 aspect ratio, for example, is a square. The first number always refers to the width, and the second number refers to the height
  • You can set this property using multiplier.
//1:2 i.e view height is 2 times greater than it's width
redView.heightAnchor.constraint(equalTo: redView.widthAnchor, multiplier: 2)

How can we set content hugging and compression resistance?

Click here to know about autolayout fundamental and CHCR

//setting Content Hugging Priority horizontally
redView.setContentHuggingPriority(UILayoutPriority(rawValue: 999), for: .horizontal)
//setting Content Hugging Priority vertically
redView.setContentHuggingPriority(UILayoutPriority(rawValue: 999), for: .vertical)
//setting Compression Resistance Priority horizontally
redView.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 999), for: .horizontal)
//setting Compression Resistance Priority vertically
redView.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 999), for: .vertical)

Available layout guides:-

Each UIView comes with a few layout guides which can also be used as anchors.

  1. LayoutMarginsGuide
  2. ReadableContentGuide
  3. SafeAreaLayoutGuide
  • Set constraints and keep the layout margins as spacing
/*
- It adds default UIEdgeInsets for the layout margin guide.
- If you want to change you can add additional edge insets by - view.layoutMargins = UIEdgeInsets(top: 150, left: 50, bottom: 50, right: 50)
- In iOS 11 and later, use the directionalLayoutMargins to define layoutMargins as:
view.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 150, leading: 50, bottom: 50, trailing: 50)
*/
// LayoutMarginsGuide for UIView
redView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor)
//ReadableContentGuide for UIViewredView.widthAnchor.constraint(equalTo: view.readableContentGuide.widthAnchor)
  • Represents the portion of your view that is unobscured by bars and other content.
  • Apple has deprecated topLayoutGuide & bottomLayoutGuide. So instead of having two dummy boxes, you now have one dummy box named safeAreaLayoutGuide on the UIView instance.
  • Want to know more about Safe Area? Read this excellent post by Evgeny Mikhaylov.
//SafeAreaLayoutGuide for UIView
redView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor)
// you can set the additionally safe area insets to view controller as:
viewController.additionalSafeAreaInsets = UIEdgeInsets(top: 150, left: 50, bottom: 50, right: 50)

Some of common error found while coding layouts:-

For example, we can’t pin the top anchor to the left anchor as they are in different axis, and it makes no sense. Attempt to do the following results in compilation issue as Swift strong type system ensures correctness.

  1. Bellow error is because of setting redView.topAnchor to view.leftAnchor. It can be fixed by changing view.leftAnchor to NSLayoutYAxisAnchor like view.topAnchor or view.bottomAnchor.
redView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
redView.topAnchor.constraint(equalTo: view.centerYAnchor)

Animate changing Auto Layout constraints:-

UIView.animate(withDuration: 1.0) { [weak self] in
self?.imageToTopConstraint.isActive = false
self?.view.layoutIfNeeded()
}

External dependency when writing constraints in code:-

There are a lot of external dependencies that say that they make it easier to write constraints. I hope that the above examples showed that it’s already quite easy to write constraints in code by making use of the default APIs. External frameworks introduce custom code patterns that might not be familiar to current and future colleagues.

Debugging Auto Layout constraints:-

  • Constraints break can be easily identified by using identifier. It can be set as constraint.identifier = identifier name
let widthConstraint = redView.widthAnchor.constraint(equalToConstant: 100)// setting identifier to the constraint.
widthConstraint.identifier = "redView width constraint"
widthConstraint.isActive = true
  • You identify the Constraint Conflicts using these identifier. Now log look like this,

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store