This workshop will be retired on May 31, 2020.
Layout Anchors9:31 with Pasan Premaratne
Using the init method on NSLayoutConstraint makes it a chore to write layout code. Thankfully that's not the only way to do this. In this video let's explore how we can use a factory class, NSLayoutAnchor, to make our code more concise and readable.
While NSLayoutConstraint instances allow you to define constraints in code, 0:00 the verbose nature of the Initializer makes you want to go back to 0:05 interface builder immediately. 0:08 This was a common complaint, so in ILS 9, Apple introduced the NSLayoutAnchor class. 0:10 NSLayoutAnchor is not a new constraint class, but a factory class instead. 0:16 If you're unfamiliar with the term factory, 0:22 it is a design pattern where you use either a class or methods to create other 0:24 classes without having to specify the exact class of the object being created. 0:30 This sounds confusing, but essentially NSLayoutAnchor creates different 0:36 kinds of constraint objects using a much more fluent API. 0:40 Allowing us to avoid the use of NSLayoutConstraint entirely. 0:44 This is a simplification of course, but the class does such a good job of hiding 0:48 the details that we can work with such a simple description. 0:52 So let's take a look. 0:55 In the previous video, we wrote out some constraints in code 0:56 using the NSLayoutConstraint Constructor or the Initializer. 1:00 So let's re-factor this code to use layout anchors instead. 1:04 So make sure you're in ViewController.swift and 1:09 the first constraint we created in here inside of 1:11 viewWillLayoutSubviews is a horizontalCenter constraint. 1:14 Let's rewrite this, and since as you will see, 1:18 the layout anchor API is more concise. 1:21 We don't need to define a constraint, assign it to a constant, 1:24 then include that constant in the array of activated constraints. 1:27 We can simply define it within the array directly, so down here. 1:31 Now when using the NSLayoutAnchor APIs, we don't use the class directly. 1:36 Remember it's a factory class that is used to create instances of other classes. 1:41 Instead, we always start with a view, or layout guide object 1:45 that we wish to constrain, and then select one of the object's anchor properties. 1:49 So let's start with the redView here. 1:54 We're creating a center X constraint so the anchor property is, so 1:59 again this is going to be a property, so centerX. 2:04 All constraints attributes that we are familiar with that are defined on 2:07 the attribute enum on NSLayoutConstraint have corresponding anchor properties. 2:11 So anywhere where over here in the previous videos where we did an attribute, 2:16 there is a corresponding anchor. 2:20 So you don't have to learn anything new, 2:22 you just have to use an anchor on a view now. 2:24 On this anchor property, we're going to call a method. 2:27 The method we call depends on the type of constraint we want to create. 2:31 This is going to be a constraint with an equal relation, the standard multiply, and 2:35 no constant value. 2:40 So we're going to hit dot and we'll say constraint equals to, and 2:41 you will see there's a bunch here. 2:45 We're going to pick this one, 2:48 constraint equal to because we don't need a multiplier, we don't need a constant, 2:50 and we don't need any of these greater than and less than stuff. 2:53 So we'll Enter. 2:56 This method takes as an argument another anchor we want to pin to. 2:58 And here we'll specify the view.centerXAnchor. 3:02 This matches a constraint we created earlier. 3:07 And now we can go ahead and delete this horizontalCenter constraint we defined 3:09 earlier, having replaced it with code that's far more concise and readable. 3:14 And that's all there is to it. 3:20 Now before we poke at the inner workings of what this line of code actually did, 3:22 let's refactor the rest of our code. 3:26 So next step is the widthConstraint. 3:28 We'll get rid of this here. 3:30 Again, we start with a view, or a layout guide object that we wish to constrain. 3:32 So redView. 3:36 The attribute in question here is the width attribute. 3:40 So its corresponding anchor is the widthAnchor. 3:43 With width constraints as we discussed earlier, 3:47 we are not establishing a relationship between two view objects, so 3:50 the method here we call is named differently. 3:54 Instead of constraint equalTo another anchor, 3:56 this time we want constraint equalToConstant. 3:59 Since the width we defined earlier was 200.0, we'll pass that in as an argument. 4:04 Again, that's all there is, far more concise. 4:10 So here we don't have to worry about a second item. 4:12 We don't have to worry about providing nil, as we did earlier, or 4:14 specifying notAnAtrribute, and so on. 4:17 Okay, now we can delete this previous width constraint. 4:20 The next constraint is a heightConstraint. 4:25 And this is essentially the same as a widthConstraint except we use the height 4:28 anchor instead of the width. 4:32 So redView.heightAnchor.constaint(equalToCon- 4:33 straint: 00.0). 4:38 For the last constraint, the bottom spacing one, 4:42 we'll use the bottom anchor on the red view and 4:45 call a method that takes a combination of both an anchor and a constant. 4:48 So, redView.bottonAnchor.constraint equalTo, and if 4:52 you look around you'll see this one that says equal to an anchor and a constant. 4:57 So here you'll say view.bottonAnchor and the constant is -50. 5:05 With that, we can delete all the constraints we defined 5:12 earlier using the Initializer on NSLayoutConstraint. 5:15 As you can see the layout anchor approach makes it much easier to write layout code. 5:19 Okay, so how does any of this work? 5:25 Ultimately, we are using constraint objects or 5:28 instances of NSLayoutConstraint. 5:31 Because this activate method, if you look at the signature of this method, 5:33 it takes in an array of NSLayoutConstraint. 5:37 And despite the fact that we are using anchor APIs in here, 5:40 there are no compiler errors. 5:42 As I mentioned earlier, NSLayoutAnchor is a factory class. 5:45 In fact, it is a generic class that defines 5:48 a set of methods to build constraints. 5:51 These were methods we use like constraint equalTo, constraint equalToConstant, 5:54 and so on. 5:59 Now are others too that we didn't use but that you should be familiar with. 6:01 Like constraint greater than or equalToConstant, so on, 6:04 less than or equal to. 6:07 When we call these methods, we didn't call them on NSLayoutAnchor class, but 6:09 on anchor properties defined on views. 6:14 If we inspect these properties, you will see that the types 6:18 are not NSLayoutAnchor but NSLayoutXAxisAnchor, 6:23 NSLayoutDimension, NSLayoutYAxisAnchor and so on. 6:27 These are sub-classes of NSLayoutAnchor that define anchors returning 6:32 specific kinds of constraints. 6:36 NSLayoutXAxisAnchor is used to create horizontal constraints. 6:39 NSLayoutYAxisAnchor for vertical constraints. 6:44 And finally NSLayoutDimension is for constraints that affect height or width. 6:48 Why three different classes though? 6:53 Remember these are generic classes. 6:55 And if you look at these signatures of the methods we use, so 6:57 the type signatures, we will look at this one right here. 7:00 You'll that they accept as arguments generic NSLayoutAnchor instances as well. 7:05 When we use an anchor property on a view object, depending on the anchor we select, 7:12 we're constrained to the types of arguments we can provide 7:16 when creating constraints. 7:20 Say we select the redViews.topAnchor, let me start typing that up, 7:23 redview.topAnchor. 7:27 This is of type NSLayoutYAxisAnchor since it’s in the vertical direction. 7:30 From there, if you call any of the constraint methods, so 7:34 let me call constraint equalTo, I don’t even need to type this out fully. 7:38 But now you can see that in the argument section 7:42 you can only provide arguments of type NSLayoutYAxisAnchor. 7:45 Now similarly, if I were to go back and type leadingAnchor.constraint, 7:49 you'll see that it automatically limits us to XAxisAnchor types. 7:55 This means that once we select a vertical anchor, like top or 8:00 bottom, we can only create constraints with other vertical anchors. 8:03 So this type checking prevents us from making mistakes, 8:07 like creating a top anchor to a left anchor constraint. 8:10 Now it's not foolprooof however. 8:13 Technically we can't create constraints that go from a leading or 8:15 trailing anchor to a left or right anchor. 8:19 But since they are both horizontal constraints, 8:22 the compiler won't catch us and prevent us from doing that. 8:24 This sort of constraint would crash at runtime. 8:27 But using these API's and a combination of a generic factory class, 8:30 we get this compile time safety. 8:35 To summarize, NSLayoutAnchor and it's related sub classes act 8:37 as factory classes, allowing us to create constraints with a much more fluent API. 8:42 The methods defined on the NSLayoutAnchor are constraint to the specified generic 8:48 sub classes when we call them anchors which provide us some degree of safety. 8:53 But ultimately, all of these messages return NSLayoutConstraint objects, 8:58 just like we created manually, so everything else remains the same. 9:03 Now that's really all there is to know about layout anchors, 9:07 layout anchors are the preferred way to write layout code these days. 9:10 And while we barely covered much of the API here, 9:14 I've linked to the auto layout cookbook workshop series in the notes. 9:18 Head over there where you'll find tons of different recipes or 9:22 examples that you can work through to get practice writing auto layout code. 9:26
You need to sign up for Treehouse in order to download course files.Sign up