I'm a software developer based in the UK. I am blogging regularly about software development & Apple

View layout in iOS 9 with Swift

The creation and handling of layout constraints via storyboards is painless and easy. Sometimes however it is necessary to create those constraints programmatically which can easily turn into a somewhat cumbersome experience. The visual format language Apple provided mitigates this but requires too much coding whenever just a few constraints are needed. That's where NSLayoutAnchor introduced in iOS9 comes in.

NSLayoutAnchor

In iOS9 UIViews have new properties like leftAnchor, rightAnchor, widthAnchor .... (see Picture 1 for an overview of the available anchors). The usage of those anchors is straightforward and very intuitive (check this playground for more sample code). All it takes is to call one of the available constraint methods on a view's anchor:

let view1 = UIView(frame: .zero)
view1.translatesAutoresizingMaskIntoConstraints = false
view1.backgroundColor = UIColor.blueColor()
view.addSubview(view1)
view1.topAnchor.constraintEqualToAnchor(view.topAnchor,constant: 10).active = true
view1.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor,constant: 10).active = true
view1.widthAnchor.constraintEqualToAnchor(view.widthAnchor, multiplier: 0.3).active = true
view1.heightAnchor.constraintEqualToAnchor(view1.widthAnchor, multiplier: 1).active = true

The last 4 lines which are solely responsible for the layout, put view1 in the top-left corner of its parentview with an offset of 10 in X and Y. Just to illustrate the ease of use of this new API, lets add a view with the same size which sits 10 points next to view1 (see Picture 2):

let view2 = UIView(frame: .zero)
view2.translatesAutoresizingMaskIntoConstraints = false
view2.backgroundColor = UIColor.yellowColor()
view.addSubview(view2)
view2.topAnchor.constraintEqualToAnchor(view.topAnchor,constant: 10).active = true
view2.leadingAnchor.constraintEqualToAnchor(view1.trailingAnchor,constant: 10).active = true
view2.widthAnchor.constraintEqualToAnchor(view1.widthAnchor, multiplier: 1).active = true
view2.heightAnchor.constraintEqualToAnchor(view1.heightAnchor, multiplier: 1).active = true
illustration1.png

Laying out views with anchors is easy when just a few constraints are needed. For complex layout rules however anchors are less suitable since each constraint requires a new line for each new statement. They are however due to their compact nature less verbose than NSLayoutConstraint's constraintWithItem and hence the better alternative.

In the picture above, I intentionally left out 2 anchor properties:  leadingAnchor & trailingAnchor. They are similar to leftAnchor and rightAnchor in their use. To be exact, when using left-to-right languages like English, left anchor is equivalent to leading anchor and right anchor to trailing anchor. However, for right-to-left languages like Arabic, left anchor is equivalent to trailing anchor and right anchor to leading anchor. It's important to keep this in mind when writing apps for several appstores. Hence it's best to follow Apple's recommendation to use leading and trailing anchors instead of their left and right alternative.

Last but not least, as attractive as those one-line layout constraint rules look like, they grow proportionally as soon as more fine-tuning is required. If for example the priority needs to be set as well,  the constraint then needs to be assigned first to a variable before setting it active. Otherwise there is no direct reference to the just created constraint.

UILayoutGuide

Before iOS9 when a layout like that in Picture 3 needed to be created, it was necessary to use helper views to manage distances among views. Since views are backed by layers, they redundantly consumed memory when they were used for those purposes. Apple recognized this and added UILayoutGuide as a lightweight alternative to iOS9 e.g.

let layoutGuide = UILayoutGuide()
view.addLayoutGuide(layoutGuide1)
layoutGuide.widthAnchor.constraintEqualToAnchor(view.widthAnchor, multiplier: 0.3).active = true
layoutGuide.heightAnchor.constraintEqualToConstant(1).active = true
layoutGuide.leftAnchor.constraintEqualToAnchor(view.leftAnchor).active = true

Layout guides are basically rectangles that can be treated like UIViews.

Conclusion

IOS9 introduced some useful additions to Autolayout. Most projects might not rely on those new features yet since they most often need to support the current and the previous version of iOS (see here for an interesting discussion about this). Nonetheless Autolayout has grown up. Although most of its problems have been tackled a year after its introduction, it's nice to see that Apple keeps improving the API by making those evolutionary changes.
 

Playgrounds cheat sheet

Staying up-to-date