This workshop will be retired on May 31, 2020.
Visual Format Language9:28 with Pasan Premaratne
There are several ways to write layout code and in this video we look at one of the more interesting ways - using format strings.
Writing constraints in code, 0:00 especially when using layout anchors, makes it very simple to layout our views. 0:02 But it's still somewhat more cumbersome than interface builder because we have to 0:06 write out a line of code for every single constraint that we want to add. 0:11 And that can quickly add up, even for a very simple layout. 0:15 There's one final aspect of programmatic AutoLayout we need to explore 0:19 that solves this problem in an interesting way. 0:23 This approach isn't new and has been around since the early days of AutoLayout. 0:26 And while we're going to take the time to learn this, 0:31 you should know that it isn't used nearly as much these days. 0:34 The final way we can build constraints is using text-based visual strings. 0:38 This approach solve the problem of verbose code, 0:44 particularly when objective c was the only option. 0:47 But now with Swift Layout Anchors and the ability to define custom operators 0:50 using text-based visual strings has fallen out of favor. 0:55 Regardless we are going to go through it because one, it is important to know, 0:59 you might run into it and you'll need to know how to tackle this code. 1:03 I am sure you have seen art work like this at some point whether it is in code or 1:07 places like Reddit. 1:11 This is commonly known as ASCII art because it's made from characters defined 1:12 in the ASCII character standard. 1:17 Just like when we use a set of characters here to make pictures, we can use a subset 1:19 of characters to draw a visual string that represents our desired layout. 1:24 AutoLayout then parses these strings and builds constraints out of them, 1:29 it's actually quite cool. 1:33 These types of constraints that we'll define, where we use a TextString 1:35 to describe a layout, is called a Visual Format Language. 1:39 So if you see references to Visual Format Language or 1:43 VFL, you'll know what that means. 1:46 I have a new Swift file in my project called VisualFormatLanguage, and 1:49 I have some static code in here to get us going along. 1:53 As always, you can grab this code from the link in the teacher's notes. 1:56 [SOUND] The layout we want to end up with looks like this. 1:59 So the first thing we're going to do in here. 2:04 So we already have a red, green, and a blue view set of colors and 2:06 added these as sub views. 2:09 So the first thing we're going to do in here is define a dictionary inside view 2:11 layout sub views. 2:15 This might seem a bit odd, but bear with me. 2:16 So we'll call this dictionary views. 2:19 In this dictionary we're going to specify, as values, 2:22 the views we want to define constraints on. 2:25 For the keys in each key value pair, 2:29 we're going to define a string that describes the view. 2:31 You can give it whatever name you want. 2:34 For reasons that I'll talk about in a second, 2:37 we're also going to explicitly set the type on this dictionary as String to 2:39 Any instead of the implicit String to View that the dictionary should get. 2:44 Okay, so remember, each key value pair is a string describing the name as a key and 2:51 then the actual view. 2:56 So, we can say redView is redView, 2:57 and then greenView : greenView, 3:02 and blueView : blueView, okay? 3:07 The reason we're doing this is because we're going to define our layout 3:12 using strings. 3:15 And in these strings, when we want to specify the redView, 3:17 we're simply going to use these keys that we've defined in this dictionary. 3:20 We'll go into more detail about how exactly auto layout is then 3:24 going to go from that string to the view. 3:27 Already it seems like a bit of additional work, but 3:30 the benefit of using visual format language is that we can create several 3:33 constraints in a single line of code by writing a sort of visual story. 3:37 To write a constraint using a FormatString, 3:42 we use a another class method on NSLyoutConstraint. 3:45 Constraints with visual format that take several arguments and 3:49 returns on array of constraints. 3:53 So the class is NSLayoutConstraint and 3:55 the class method is constraintwithVisualFormat. 3:57 The first argument is the format string that describes our layout. 4:01 For now, let's just pass in an empty string. 4:05 The next parameter named, options, takes an option set that describes the attribute 4:08 and the direction of layout for all our objects in the visual format string. 4:14 We'll touch on this later, for now, 4:19 we're going to put in a set of brackets to denote and empty set. 4:20 The next parameter named, metrics, 4:25 takes another dictionary of constants that appears in the visual format String. 4:27 We'll add to these in a second, so for now just pass in nil. 4:32 Finally, we come to our views argument. 4:36 So this is where we pass in the dictionary we created. 4:38 This allows us to use the keys in the dictionary as a way to reference the views 4:42 in the FormatString that we create. 4:46 AutoLayout will then go through this dictionary and 4:49 find out which view we're talking about. 4:51 Notice here that the type of String to Any and 4:53 that's why we had to put this explicit type of String to Any. 4:56 Had we put a String to UIView the implicit type, we would have gotten some issues. 4:59 Nothing that would have stopped us from running our code but, 5:04 I don't like yellow lines everywhere. 5:07 So let's pass in our views here. 5:09 We're going to start simple here and work with just the redView by defining width. 5:12 So let's go back to this first argument, the FormatString. 5:18 Inside this string, just follow along with me for now. 5:22 Write an upper case 5:25 H:[ RedView(200)]. 5:30 And just like that, we've defined a width constraint on the redView. 5:39 There's a lot of magic going on here, so let's pass this string. 5:43 The first H and 5:48 a colon indicates that this format string specifies a horizontal constraint. 5:49 For a constraint in the vertical axis, we'd use a V and a colon. 5:55 If we were to omit the H or the V and a colon 6:00 on AutoLayout would default to creating constraints in the horizontal direction. 6:03 So really this is unnecessary, but this is more explicit. 6:07 Inside a format string, we specify a view inside square brackets. 6:11 So here by placing the key redView inside a set of square brackets, 6:15 we've indicated that we have a constraint that involves a view named redView. 6:21 To give the redView a width constraint, all that's left to do now 6:26 is to specify in parentheses the width of the redView. 6:32 And we do that inside of the squared brackets and 6:36 right beside the name of the view. 6:38 So how does the system know that this is a width constraint? 6:41 Well, first this is specified in the horizontal axis, and 6:44 second because the value is described immediately after the view in parenthesis. 6:48 So this means this is either a height or a width. 6:53 And because this is the horizontal axis, AutoLayout knows that this is the width. 6:58 When we specify redView inside the format string, 7:04 AutoLayout known which view we refer to because it uses this 7:06 string as a key in the views dictionary and gets the actual view as a value. 7:11 So that's the entire purpose of the views dictionary. 7:16 The first metric that we're using here 7:19 is the 200 value to specify it with constraint. 7:22 At 200 inside parentheses in the format string 7:26 isn't a very meaningful description. 7:29 So let's improve on this. 7:31 To use descriptive names for 7:33 constants in the format string, we define another dictionary that we call metrics. 7:34 So just like view, we'll name this metrics and give it a type, String to Any, okay? 7:39 And in here, we specify a string that serves as a key for 7:45 the constant that we want to specify. 7:48 So here, we'll say redViewWidth has a value of 200 and 7:51 now we can pass in this metrics dictionary in to our method and 7:57 then use that key inside of the format string. 8:03 So instead of saying 200 we'll say RedViewWidth. 8:05 Now, before we move on to specifying more constraints, 8:11 we need to add these constraints to the view. 8:14 Because this method unlike any that we've viewed so 8:17 far, because this method constraints with the visual format 8:20 allows us to specify many constraints in a single string. 8:24 The return value on the method is an array of NSLayoutConstraint 8:28 rather than a single constraint. 8:32 Now, as we've talked about before, 8:35 there are many ways we can add constraints to the actual view layout. 8:37 So let's summarize it. 8:40 In this case, we can call view.addconstraint. 8:42 Earlier we looked at a single constraint. 8:46 You'll notice that also takes an array of constraints. 8:48 We can also assign the returned constraints to a constant and 8:50 pass that in as an argument to this or 8:55 on the NSLayoutConstraint activate method that we've been using. 8:57 Finally, since this is an array we can map 9:01 over each constraint into the array using $0 to represent it. 9:05 And then we can set the isActive property to true, 9:11 which goes through all the constraints and activates that. 9:14 Okay, let's do that for now. 9:18 So this was our first horizontal constraint on the redView. 9:20 Let's take a quick break here and in the next video we'll continue to build on this 9:24
You need to sign up for Treehouse in order to download course files.Sign up