Understanding the iOS 7 Auto Layout Visual Format Language

PreviousTable of ContentsNext
Implementing Cross-Hierarchy Auto Layout Constraints in iOS 7Using Storyboards in Xcode 5


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book


The third and final option for the creation of auto layout constraints involves a combination of code and the visual format language. The goal of this chapter is to provide an introduction to the visual format language and to work through some code samples that demonstrate 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 Objective-C 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 constraintsWithVisualFormat 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 that is being created.

Visual Language Format Examples

By far the easiest way to understand the concepts behind the visual format language is to look at some examples of the syntax. 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)]

Using similar syntax, the width of one view can be constrained to match that of a second view:

[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]-|

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book


Using the constraintsWithVisualFormat: Method

As previously described, visual language format based constraints are created via a call to the constraintsWithVisualFormat method of the NSLayoutConstraint class. There are, however a number of other arguments that the method is able to accept. The syntax for the method is as follows:

[NSLayoutConstraint constraintsWithVisualFormat:<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 that are to be created. The <options> are required to 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 NSLayoutFormatAlignAllLeft, NSLayoutFormatAlignAllRight, NSLayoutFormatAlignAllTop, NSLayoutFormatAlignAllBaselines etc).

The <metrics> argument is an optional NSDictionary object containing the corresponding values for any constants referenced in the format string.

Finally, the <views dictionary> is an NSDictionary object that contains the view objects that match the view names referenced in the format string. The iOS 7 SDK provides a convenience macro that can be used to construct this dictionary for the objects referenced in the format string, for example:

NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings (mybutton1, mybutton2);

When using a visual format string that will result in the creation of multiple constraints, the options should include an alignment directive such as NSLayoutFormatAlignAllBaseLines.

Since the method is able to 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
UIView *superview = self.view;

//Create a label
UILabel *mylabel = [[UILabel alloc]init];

[mylabel setTranslatesAutoresizingMaskIntoConstraints:NO];
mylabel.text = @"My Label";

//Create a button
UIButton *mybutton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[mybutton setTitle:@"My Button" forState:UIControlStateNormal];
[mybutton setTranslatesAutoresizingMaskIntoConstraints:NO];

//Add the button and label to the superview
[superview addSubview:mylabel];
[superview addSubview:mybutton];

// Get the views dictionary
NSDictionary *viewsDictionary = 
         NSDictionaryOfVariableBindings(mylabel, mybutton);

//Create the constraints using the visual language format
NSArray *constraintsArray = [NSLayoutConstraint 
         constraintsWithVisualFormat:@"|-[mybutton]-[mylabel(==mybutton)]-|"
         options:NSLayoutFormatAlignAllBaseline metrics:nil 
         views:viewsDictionary];

//Work through the array of constraints, applying each to the superview
for (int i = 0; i<constraintsArray.count; i++) {
        [superview addConstraint:constraintsArray[i]];
}

Summary

The visual format language allows auto layout constraints to be created using sequences of characters that have been designed to visually represent the constraint that is being described. Visual format strings are converted into constraints via a call to the constraintsWithVisualFormat 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.


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book



PreviousTable of ContentsNext
Implementing Cross-Hierarchy Auto Layout Constraints in iOS 7Using Storyboards in Xcode 5