The third and final option for creating Auto Layout constraints involves a combination of code and the visual format language. This chapter aims to introduce the visual format language and work through code samples demonstrating the concept in action.
Introducing the Visual Format Language
The visual format language is not a new programming language in the way that C++, Java, and Swift are all programming languages. Instead, the visual format language defines a syntax through which Auto Layout constraints may be created using sequences of ASCII characters. These visual format character sequences are then turned into constraints by passing them through to the constraints(withVisualFormat:) method of the NSLayoutConstraint class.
What makes the language particularly appealing and intuitive is that the syntax used to define a constraint involves characters sequences that, to a large extent, visually represent the constraint being created.
Visual Format Language Examples
The easiest way to understand the concepts behind the visual format language is to look at some syntax examples. Take, for example, visual format language syntax to describe a view object:
[myButton]
As we can see, view objects are described in the visual format language by surrounding the view name with square brackets ([]).
Two views may be constrained to be positioned flush with each other by placing the views side by side in the visual format string:
[myButton1][myButton2]
Similarly, a horizontal spacer between two view objects is represented by a hyphen:
[myButton1]-[myButton2]
The above example instructs the Auto Layout system to create a constraint using the standard spacing for views. The following construct, on the other hand, specifies a spacing distance of 30 points between the two views:
[myButton1]-30-[myButton2]
By default, constraints of the type outlined above are assumed to be horizontal constraints. Vertical constraints are declared using a V: prefix. For example, the following syntax establishes a vertical spacing constraint between two views:
V:[myLabel]-50-[myButton]
For consistency and completeness, horizontal constraints may, optionally, be prefixed with H:. The width of a view can be set specifically as follows:
[myButton(100)]
Alternatively, inequality can be used:
[myButton(<=100)]
The width of one view can be constrained to match that of a second view using a similar syntax:
[myLabel(==myButton2)]
When using the visual format language, the superview of the view for which the constraint is being described is represented by the | character. For example, the following visual format language construct declares a constraint for the myButton1 view that attaches the leading and trailing edges of the view to the left and right edges of the containing superview with a spacing of 20 and 30 points, respectively:
|-20-[myButton1]-30-|
The language also allows priorities to be declared. The following excerpt specifies that the width of myButton1 must be greater than or equal to 70 points with a priority value of 500:
[myButton1(>=70@500)]
Of particular importance, however, is the fact that the language may be used to construct multiple constraints in a single sequence, for example:
V:|-20-[myButton1(>=70@500)]-[myButton2(==myButton1)]-30-[myButton3]-|
Using the constraints(withVisualFormat:) Method
As previously described, visual language format-based constraints are created via a call to the constraints(withVisualFormat:) method of the NSLayoutConstraint class. However, there are several other arguments that the method can accept. The syntax for the method is as follows:
NSLayoutConstraint.constraints(withVisualFormat: <visual format string>, options: <options>, metrics: <metrics>, views: <views dictionary>)
The <visual format string> is, of course, the visual format language string that describes the constraints to be created. The <options> values must be set when the constraint string references more than one view. The purpose of this is to indicate how the views are to be aligned, and the value must be of type NSLayoutFormatOptions, for example, .alignAllLeft, .alignAllRight, .alignAllTop, .alignAllLastBaselines, etc.
The <metrics> argument is an optional Dictionary object containing the corresponding values for any constants referenced in the format string.
Finally, the <views dictionary> is a Dictionary object that contains the view objects that match the view names referenced in the format string.
When using a visual format string that will create multiple constraints, the options should include an alignment directive such as NSLayoutFormatOptions.alignAllLastBaseLines.
Since the method can create multiple constraints based on the visual format string, it returns an array of NSLayoutConstraint objects, one for each constraint, which must then be added to the appropriate view object.
Some sample code to create views and then specify multiple constraints using a visual format language string would, therefore, read as follows:
// Get a reference to the superview let superview = self.view //Create a label let myLabel = UILabel() myLabel.translatesAutoresizingMaskIntoConstraints = false myLabel.text = "My Label" // Create a button let myButton = UIButton() myButton.backgroundColor = UIColor.red myButton.setTitle("My Button", for: UIControlState.normal) myButton.translatesAutoresizingMaskIntoConstraints = false // Add the button and label to the superview superview?.addSubview(myLabel) superview?.addSubview(myButton) // Create the views dictionary let viewsDictionary = ["myLabel": myLabel, "myButton": myButton] // Create and add the vertical constraints superview?.addConstraints(NSLayoutConstraint.constraints( withVisualFormat: "V:|-[myButton]-|", options: NSLayoutConstraint.FormatOptions.alignAllLastBaseline, metrics: nil, views: viewsDictionary)) // Create and add the horizontal constraints superview?.addConstraints(NSLayoutConstraint.constraints( withVisualFormat: "|-[myButton]-[myLabel(==myButton)]-|", options: NSLayoutConstraint.FormatOptions.alignAllLastBaseline, metrics: nil, views: viewsDictionary))
Summary
The visual format language allows Auto Layout constraints to be created using sequences of characters designed to represent the constraint being described visually. Visual format strings are converted into constraints via a call to the constraints(withVisualFormat:) method of the NSLayoutConstraints class, which, in turn, returns an array containing an NSLayoutConstraint object for each new constraint created as a result of parsing the visual format string.