Implementing the compact size layout

To implement the compact size layout, we'll use VFL and anchors. Anchors are fairly straightforward, so let's have a look at the implementation right away and discuss them later.

First, add the following two variables that will be used later to activate and deactivate the compact size constraints:

var compactWidthConstraint: NSLayoutConstraint! 
var compactHeightConstraint: NSLayoutConstraint!

These variables will be set in viewDidLoad, and we're using implicitly unwrapped optionals for them. This means that we must set these variables before attempting to use them, otherwise the app will crash due to an unexpected nil value.

You often want to avoid implicitly unwrapping optionals. Using optionals without implicit unwrapping enforces safety because you need to unwrap these values before attempting to use them. However, in some cases, you want your program to crash if a value isn't set; for instance, when there's no sensible way to recover such a missing value. Scenarios like these are very rare, and you should use implicit unwrapping with great caution. In this example, it's used for brevity.

The following code should be added to the viewDidLoad method:

let views: [String: Any] = ["contactImage": contactImage, 
"contactNameLabel": contactNameLabel]
var allConstraints = [NSLayoutConstraint]()

compactWidthConstraint = contactImage.widthAnchor.constraint(equalToConstant: 60)

compactHeightConstraint = contactImage.heightAnchor.constraint(equalToConstant: 60)

let verticalPositioningConstraints = NSLayoutConstraint.constraints(
withVisualFormat: "V:|-[contactImage]-[contactNameLabel]",
options: [NSLayoutFormatOptions.alignAllCenterX],
metrics: nil,
views: views)

allConstraints += verticalPositioningConstraints

let centerXConstraint = contactImage.centerXAnchor.constraint(
equalTo: self.view.centerXAnchor)

allConstraints.append(centerXConstraint)
allConstraints.append(compactWidthConstraint)
allConstraints.append(compactHeightConstraint) NSLayoutConstraint.activate(allConstraints)

In the preceding code snippet, we created a dictionary of views, which is used later in VFL. We will also instantiate an empty array of constraints. This array will be used to activate all the constraints at once. The following lines assign values to the variables you added before adding this code snippet. These lines make use of the anchor technique to add constraints. You'll notice that the syntax is fairly straightforward. The constraint method is called on the anchor we wish to use, and the desired value is passed as an argument.

The vertical positioning is defined in VFL. A string is passed that vertically aligns the views with standard spacing. There's also an option passed to align all views involved on the x axis so they're centered, and finally the views dictionary is passed in. This dictionary is used to map the string values in the format string to the views we want to lay out. The resulting constraints are then merged with the allConstraints array.

Next, the contact image is aligned to the main view's x axis by using the anchor technique again. Finally, the three constraints that were created using anchors are added to the list of constraints and all of the constraints get activated at once. If you test your app on an iPhone now, everything should work out as expected.