iosdev

No headache: auto layout tips in Interface Builder

Recent versions of Xcode and Interface Builder are great visual tools to build auto layout UIs.

I wrote previously how to setup your main views so that embedding properly respects safe areas on whatever device it’s being run on. The key thing: setup inner constraints towards VC.view to use superview margins. Easiest way to do this is to:

  1. add one UIView as direct child of VC.view
  2. setup constraints of that view so its edges are all connected to VC.view’s margins
  3. All your content then goes into that “real” content view and you are set

This will solve at least 90% of layouts you’ll ever need to do.

Don’t forget an older tip about setting priority 999 for some of the sides of realContentView.


Another great guideline: when you have a series of child sibling views inside a container, either horizontal or vertical, your job will be much easier if you prioritise making constraints among siblings and avoid superview as much as possible.

Between vertical siblings, it looks like this:

Few things:

Or you can use UIStackView for this, although I find that component useful only with repeating identical views. In all other cases it’s more trouble than it’s worth. Additionally in case you want to create a layout that autosizes per contentSizeCategory, then stack views can make that impossible, depending on the layout.


Speaking of dynamic type, always, always use Text styles for all your UILabel, UITextField, UITextView etc. And make sure to set this “Automatically Adjusts Font” checkbox:

and make sure to set Lines: 0 so the text is fully visible regardless what content category size is used by end customer.

UIButton sadly does not have this option, but you can enforce it for its titleLabel:

You’ll need to include this simple extension somewhere in your code:

extension UIButton {
	///	Allows automatic response on contentSize change (dynamic type)
    @IBInspectable
    var adjustsFontForContentSizeCategory: Bool {
        set {
            self.titleLabel?.adjustsFontForContentSizeCategory = newValue
        }
        get {
            return self.titleLabel?.adjustsFontForContentSizeCategory ?? false
        }
    }
}

for that option to appear in Interface Builder.

For buttons, also make sure to use greaterThanOrEqual height constraint:


Final tip for today: IB does not have easy ability to setup rounded corners that are so prevalent in many designs, especially for buttons and various containers. Thus many devs resort to using this in code:

textView.layer.borderWidth = 1
textView.layer.borderColor = UIColor.lightGrey.cgColor
textView.layer.cornerRadius = 4

You can use runtime attributes for this, in the Identity panel (rather strange place for it):

The code above is almost always followed by this file as well, to actually have those rounded corners rendered:

textView.layer.masksToBounds = true

This line is also not needed as the same thing is achieved by simply setting “Clips to bounds” on View subsection in the Attributes panel.