Tools • iOS, OS X • 56:16
Interface Builder makes it easy to create world-class interfaces using the design canvas. Learn how to use storyboards to arrange the views of your app, use Auto Layout to adapt to changes, and see how to easily make connections between your UI and your implementation on both iOS and OS X.
Speakers: Kevin Cathey, Quinn Taylor
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript has potential transcription errors. We are working on an improved version.
[ Applause ]
I could have made a joke and said that was unowned but I won't. So this session is called "What's New in Interface Builder" or, as we were joking earlier, maybe "What Isn't New in Interface Builder." We have all kinds of great stuff for you guys today. And, so, my name is Kevin Cathey.
I'm one of the Interface Builder Engineers and me and my colleague Quinn, who'll be joining us later, are going to be walking you through some of what's new. Now we're going to show you some stuff that you might not have seen yet. And we're also going to go into more detail about some of the things that you have seen so far at this conference.
So what we have today is... conveniently falls into a couple of themes, themes that you're going to be -- have been familiar with so far in the conference. The first one is Liveness. Now I don't know about you but I like seeing what I'm working on. And so as I work on my code we have features to bring your content, your code, your custom stuff right into the Interface Builder canvas. I think we really want to help you guys get to your vision faster and to have some fun while you do it, too.
Next is Adaptability. And I love this about our platforms. It's all the places that your apps can run. Let's think about it. We've got iPhone, iPad, Portrait, Landscape, OS X, iOS, and then throw in all the languages, too. Don't you love getting those bugs that are like, hey, there's this bug in this language? And I look at it and I'm like I haven't heard of that language and I just think that's something that's great about our platforms -- and as application developers you're probably all well aware of this.
Third is Power & Parity. iOS and OS X have taken some great steps toward each other this year and I think one of the places that this is really illustrated best is in Interface Builder. And so we've got some tools to help you seamlessly work between both of our platforms using really familiar technologies and workflows.
So what's our plan for today? How are we going to do this? Well, my co-worker started an app and then he conveniently left for vacation this week. And so he didn't have a chance to finish it. So we're going to finish it for him on stage. And here's the ironic thing: the app is actually about going on vacation and sharing your photos while you're on vacation and rating those. And so we're going to get to look at my co-worker's photos as he enjoys a drink by the beach and Quinn and I give this presentation.
So we have a list of sites here. That little ring on the outside is showing, kind of, the popularity of that particular destination. Hawaii and London -- apparently great places to go -- I've never actually been to either of those. But New York -- apparently not the most fun place to visit. It must be that the pizza isn't as good as Chicago.
[ Grumbling, cheering and Applause ]
Now if I tap on one of these sites it's going to slide over and give me a little slideshow. I can rate my photos. And then, here's the iPad version, and you might notice a few little differences here. So, for one, we have a caption, and then, two, that rating is kind of [whisking sound] moved over to the side there.
I'm also a photo nerd so I love to know how you took your photo. So if you tap that little Details button, you get a popover with some location data and things like the shutter speed and f-stop. So I think the best way to do this is just to jump into a demo and start making this app awesome.
All right. So I have my storyboard here and I have the mockup that I showed you earlier from my designer, just as kind of a reference, and we'll use it as we go through our presentation. So in terms of strategy and kind of starting your app: the thing that I like to do, personally, is I like to get all my views laid out first and then kind of fill in the custom content. So let's start by adding constraints for our table view cell here.
This box is going to our -- that circle tile view that we'll fill in a little bit. There's a couple of ways to add constraints in Interface Builder. One, I can just easily control-drag to add, like, a spacing constraint for this view. I can also use the constraint popover here, and this gives me some additional features for being able to pick constants right on the fly, pick a different object to constrain to, things like that.
So now that our tile view has got position and height, well, what about width? Well, we could add an explicit width constraint but then if I were to go change the height of my table view cell, I've got to go update it in all these different spots. So what I really want to express is just that this view should have the same width as the same height. And this is what's new since last year, which is the ability to create aspect ratios.
With the tile view now in the spot that we want it, let's work on these labels. So I'm just going to grab the label and just drag it up in this spot, in the position here. And I can create multiple constraints at once using control-drag by holding the shift or the command key and then just hitting return.
Now if I look back at my mockup, you can see that the text is really not centered with the tile view. It's kind of like the bottom of the text isn't in the center this particular tile view. So now what we can do, new since last year, is we can actually go ahead and change the attributes involved in my constraint.
If I just open up the Attributes Inspector for my constraint, you can see now I can see the Items and their attributes, and I can just go ahead and change this from Center Y to Bottom, which is going to move it down to the other side. But one thing you'll notice is that it didn't do exactly what I expected.
So what's going on here? Well, one of the things that I notice is that I was thinking about it in terms of the label, not in terms of the view. So another thing that our Inspector gives us is the ability to reverse the pieces of the constraint in a way that makes sense to you. So let me undo that change.
And if I open this up again, I can select Reverse First and Second Item, and it just flips the constraint. This is mathematically equivalent to the other constraint but I can express it in a way that makes sense to me. And now I can say, okay, the label's Bottom should be at the View's Center Y.
Now one new field that you might have noticed here is the Multiplier. So this is what enables things like aspect ratios and also proportional sizing constraints and there's a couple of different ways I can insert a multiplier depending on my situation. So if I'm thinking about it in terms of an aspect ratio, I can do something like 1:4.
And you can see that now that label's Bottom is in a ratio of 1 to 4 with the Center Y of my tile view. But you know what? Fractions might make more sense to me so I'm going to use a fraction instead. So I can just type in a fraction. Or, of course, decimal numbers are also applicable as well.
So our Title Label is now in the right spot. So let's do this Sub-Label. So I can just drag this into position. And I'm just going to do two more constraints to get my views all laid out. And I can show this by resizing my Table View. Now, one of the things I love about getting to show Xcode is giving you guys a few tips and tricks for being even more productive in Xcode. So this is going to be Pro Tip Number 1. If I hold shift when I right-click in the canvas it will give me a menu of everything under the mouse at the point that I clicked.
So if I want to quickly get to my Table View cell, I just do that and select it and now I'm ready to go. If I resize my Table View cell, you can see those constraints, they're doing exactly what I want. I'm going to go ahead and undo that change.
All right. So, with our views in place, we're ready to start filling in that custom view. And you've already seen our Custom Views feature showed a couple of different times. What I'm going to do now is I'm going to show you the steps necessary to have your content showing up Interface Building from start to finish, and show you, I mean really, how easy it is.
The first thing we need to do, Step 1 of 4, is we're going to create a custom framework. Frameworks are in OS X and are new in iOS with iOS 8. So I'm going to jump to my Project Editor here. I have my list of targets, and I'm going to add a new target. We want a Cocoa Touch framework.
So I'm going to call this SiteRateKit. (The name of our app is SiteRate.) And I'm choosing to embed this in my iOS application. It's going to do two things: one, it's going to link my application against this framework, and; two, when the application builds, it's going to copy that framework into the app bundle. So let's go ahead and create that framework. And that's it. I have a custom framework and it's all ready for me.
Now Step Number 2 in getting your content to show up in Interface Builder is to create a subclass of UIView (or NSView if you're on the Mac). So I can just right-click on my group here, choose New File. I want a Cocoa Touch class. And I'm going to call this SiteTileView. Subclass UIView. And we're going to use Swift as our language. I just want to make sure this is added to the right target. You want to make sure to add it to your framework target.
And now our class is created. So two steps down already. The third step is to tell Interface Builder that this class can display custom content in Interface Builder. And I can do that by marking the class as @IBDesignable. If I'm in Objective-C, the attribute just looks like that.
So, Step 3 is done. Our class is Designable, our framework is created. And the final step is to simply tell Interface Builder that an instance of a view in my storyboard should actually be this class. So I'm going to go back to the storyboard, just using the recent files here.
And let me go ahead and select my tile view. I'm going to open the Identity Inspector and now I can just type in that tile view class that I just created. Interface Builder will auto-complete it for me. And now that's everything that I have to do to get my content showing up in Interface Builder. It's super, super easy.
Now, of course, nothing is showing up yet because we haven't written any code, but we're going to get there. So, speaking of which, let's actually now go ahead and create some code for our view. So I want to show the code for my view side-by-side with my storyboard, and that's really easy. To open my class I'm going to show you another Xcode Pro Tip: Number 2.
If I option-click this file, many of you know that it will open in a new assistant or in a new tab, based upon how your preferences are set. But if I hold option-shift and click, I get a little chooser view. And this chooser allows me to pick the destination of where I want this file to open.
I can target a new split, a new tab, a new window, I can even target splits in tabs that aren't even open. So, very, very flexible to get to where I want to open this file. I'm just going to create it in a new split side-by-side with my storyboard.
All right. So, there's a couple different ways that you can create your custom views. And the way that we're going to do that today is we're going to create our custom view by composing it of smaller components. And these components are either subviews like UILabel, UIImageView or layers. And we're going to use layers today.
If I were to implement drawRect, that's not going to get us the best performance; whereas, using sublayers and subviews is going to get us really good performance. So I can just go ahead and delete this code here. And we're going to start creating our view (if we go back to our mockup here) by working on these rings on the outside. So I'm going to start with this grey ring and then fill it in with a colored one.
So let's create a new shape layer on this, set it as a property. And you can see it's giving me an error because I need to import the module that contains the core animation classes. And I want to create this thing. A really convenient place to create this is in an override of layout sub-views.
First I want to call super which will make sure that all my subviews have the right size. And then, if I haven't created the ring layer yet... I'm going to go ahead and create one, add it to the layer of my view. And then, of course, we want to make sure that we position it in the right place.
So now we have a layer, let's do something interesting with it. I'm going to close the utility area to give myself a little bit more space. So let's create a Bézier path and we're just going to make this be a circle. And then let's set this as the shape of my shape layer. And there, Interface Builder is showing me the result of my code so far.
[ Applause ]
Responds SUPER-fast, which is just great. So now I don't really want a solid circle, right? We want to create a ring. And so CAShapeLayer has a feature that allows me to stroke the outside of the path. And so I'm going to go ahead and turn off the fill color to set a line width and set the stroke color to black.
Now because my content is showing live in Interface Builder, I can see that I've already made a mistake. For those of you familiar with BezierPath, you'll know that when you have a stroke, half of it draws outside the path and half of it inside the path. So, actually, I want to inset my path by half of the linewidth. Now I know that I'm going to use my linewidth a lot, so let's create a new property for it.
And now I can inset my rectangle by that amount and I'll make sure that I use it in both spots. And now my shape is looking much better. So the last thing we want to do is we want to fill it in with that color that our Designer gave us, so we'll fill that in. And, wow, that looks really, really light. Hmm. I'm going to change this to 0.3. Designers aren't always right.
So now that my ring layer -- [applause] -- [laughs] I love all of our designers. Now that our ring layer for the background's looking pretty good, let's fill it in with some color. I'm just going to do the exact same thing, pretty much. The only difference I'm going to do with this other ring layer is I'm just going to rotate it by 90 degrees so that when we fill in our rating it's going to come from the top of the circle and not out of the side. So I want to drive my shape layer now by an actual rating. So let's create a new property which is the rating.
And now we want to actually update our layer based upon this rating, so I'm going to use a feature of CAShapeLayer that allows me to set the, kind of, the progress of the stroke. And I'm going to do it in a new method, because I'm going to call this row in a bunch of different spots.
So one of these spots that I'm going to call this from is from changing the rating itself. It couldn't be easier now to react to property changes with Swift's new Property Observers. So all I have to do is just say that when this rating did change I can just go ahead and call that method that updates my shape layer. And I'm also going to call it inside of here just in case we haven't actually changed those properties yet. And now my shape layer is looking exactly how I want it, so far.
Now it's really common when you're creating different types of custom views that you want to have properties that you expose that people can change, either for your code or even within Interface Builder. And Interface Builder makes that really easy with a new feature called Inspectables. So if I go up to my rating property here and mark it as IBInspectable... This is a flag for Interface Builder that says, "Hey, this property? I want you to show it in Interface Builder" just like all the other properties that you edit on your views. So if I jump back to Xcode and I open the Inspector, you can see that that rating is showing up and I can edit it and it reflects instantly in the canvas.
[ Applause ]
So you might be wondering, well, what can I use with Inspectables? You can use all kinds of different types for Inspectables. Now the way that Inspectables works is that you might be wondering "well, where does all the data get stored?" Inspectables takes advantage of the user-defined runtime attributes that we've had for a couple of releases of Interface Builder.
You can see that the rating that I just set is showing up here. Now it's important that we are using user-defined runtime attributes for Inspectables because it means that you don't have to worry about where to store this data and how to encode it. We take care of all of that for you at design time and at runtime. The different types that I can use for Inspectables are anything supported by user-defined runtime attributes: Booleans, strings, numbers, values like points and sizes and rects and even images, which is new this year.
Love it. So Inspectables I think are great for exposing properties of your views that you can edit. But I think it's also really helpful for helping you develop your views. So there's two ways that I see this. The first thing is it helps you just validate the changes that you're making, especially as you're experimenting with new types of things.
So I want to change the color of my rating based upon how good that rating is. Red means "you better catch up," and green might be "well done!" So let's go ahead and change the color of our stroke based upon that rating. And I'm using a new switch statement in Swift to accomplish this.
And now you can see that Interface Builder is doing the right thing in terms of the color. Now I'm going to switch back to Interface Builder so I can edit the Inspectable. And I'm going to show you Xcode Pro Trip Number 3. I like to navigate sometimes -- a lot of times -- without the mouse. And I can jump around within Xcode and put the focus in different editors using command-J.
If I hit command-J it gives me a little chooser and I can pick which editor I want to have focused. So in this case I want to jump-focus back to the Interface Builder editor. So I can just go ahead and hit command-J. It picks the primary; hit return. And now you can see I'm seeing my inspectors for Interface Builder. I can jump to the attributes inspector with command-option-4. And now that field's in focus and I can try out our colors. And everything looks to be behaving as expected.
Now the next place that I can use Inspectables in terms of playing with my views is also in just experimenting with different types of values. So I haven't decided yet on my line width. 10 might work, or it might not be the right thing. So let's mark that as Inspectable.
I'm going to jump back to Interface Builder using command-J. That language is showing up. And let's try a new value: 12. Whoa, that is pretty thick. So let's just, you know, come back down here. 5's a little small. What about 6? Yeah, 6 looks pretty good to me. So it's very, very easy to experiment with your custom views when using them with an Interface Builder. Now I'm also going to show you just how live these views are. I'm going to go ahead and resize my table view again.
And you can see, as I'm resizing it, it's just perfectly redrawing my view. It's interacting with it just like any other view that's inside of Interface Builder. Let me go ahead and undo that change. Okay. So our rings are looking pretty good. Let's go ahead and fill in that image.
So I'm going to create a new layer for my image. I'm also going to declare a property that I can set for my code to update that image. Now, I want to put an image in there, and so let's go ahead and set that on our layer. I'm going to come back down to our layer properties here.
And, actually, I don't think I want to create this inside of our property, so let's actually go ahead and undo that, and let's create the layer first. And I'm going to do that inside of our layout subviews. That's looking a little better. That's a better place to do it.
But let's update it down here in our layer properties. So you can see Interface Builder is -- all I'm doing is I'm just I'm drawing a square and then I'm drawing a circle and masking it. And now we can set the image as the contents of that square layer behind it.
So let's get an image to set inside of here. Now I don't want to ship any images with my actual framework (the images that I use for testing, right?) because that would just bloat the framework. What I'd like to do is be able to reference an image that's in my project without actually putting it in a target.
And Interface Builder provides a great place to do this and a great way to do this through prepareForInterfaceBuilder. So this is a method that gets called after your views are initialized inside of Interface Builder, and allows me to do any kind of design-time setup. Again, this only gets called at design-time.
Now I have some images in my projects, some test images. Let me show them to you over here in this folder. And these aren't in any target. They're just some images that my designers gave me to help me test to make sure that my app is doing the right thing. So I'm going to go and reference one of these.
But I want to -- so, I could pass a, you know, an absolute path and generate an image. But I'm going to do it in a way that's going to make sense for my entire team. So Interface Builder will actually pass the paths to your projects through the environment and allow you to actually take advantage of the resources in your project.
So let's go back here and let's go ahead and look at what that looks like. So inside of our environment there is an "IB-PROJECT-SOURCE-DIRECTORIES" string. That's just a bunch of project directories concatenated with a colon. And I can split those up and go ahead and actually get the strings. So I only have one project path so I'm just going to go ahead and grab the first one and I can get the path relative to my project just by appending that test image's -- and, that image name.
And then we can go ahead and create the image. And it should -- hmm. It should show up here any second. Huh. Well, this isn't exactly looking right to me. I think I must have missed something. Wouldn't it be great if I could just debug my view right in the canvas?
- Yeah.
- Well, with live views you can. So I'm going to set a breakpoint on my image here. Go back to Interface Builder and select my tile view. And from the Editor Menu I can just select Debug Selected Views. And this is going to attach to Interface Builder and allow me to actually debug my custom view just like any other debug session.
So I can see here the -- it looks like I'm getting inside of here, so I'm getting a project path. Let's go ahead and step over and let's see what that image is. You can see the LDB is automatically printing out the fact that this is an optional type and that the optional type actually has something in it. So let's see what that image is. And, yep, sure enough, we got an image, so what's going wrong here? Well, let me put a breakpoint where we actually set our image contents. And let's hit Continue.
And, oh, interesting. That method never actually gets called. What I must be doing is I must have forgotten to actually update my image property in my image layer when the image property changes. If I scroll up -- oh, yep, sure enough. I forgot to use a property observer to make sure that my image layer was going to get updated when the image changed. And there you go.
So Interface Builder provides lots of different ways for you to be able to design your views using something like prepareForInterfaceBuilder in these IB Project Source Directories: you can see your custom images, you can debug them... but there's even more you can do. So let's go ahead and close the debug area here. I'm going to jump over to a different View Controller now.
And we have this Rating View which is showing us the number of stars for our particular image. Now this Rating View has an Inspectable. It's called Star Rating. And I'm going to go ahead and change this to 3.5. And when I zoom back out and zoom in instead on our rating layer, you can see -- oh, yeah. That label there is overlapping our star. Well, why is that? Well, we have this explicit width and height constraint so that the Rating View doesn't have a chance to grow it at whatever size it is. So let's just go ahead and delete those. We don't need them.
So, again, delete those. And now Interface Builder is helpfully telling me that my view is ambiguous. It doesn't have enough constraints. Now for those of you familiar with Auto Layout, you'll know that there's a method called Intrinsic Content Size which allows you to define a size-to-fit-size for my view.
Well, I can take advantage of that right inside of Interface Builder. If we go to our Rating View Class, and I'm going to open that using Open Quickly. Site Rating View. And I'm going to use my little option-shift to target the assistant here. And we'll scroll to the bottom of the file to add our new code.
So I've overwritten our intrinsicContentSize method and now Interface Builder is going to recognize that method is there. It's going to call it just like it normally would at runtime. And now it's showing me that my view can grow to fill the size of the stars and the intrinsic content size of my label, and I can just put it right into place. And it's also telling me that my view is now no longer ambiguous. I'm all good to go. It's executing my code and using that intrinsicContentSize override to figure out which constraints need to be there.
Now for those of you who are "pixel perfectionists," you might realize that that caption is actually 1 point off from this label in terms of being aligned. I would like to be able to align these two things by their baseline but my Rating View is a custom view that has stuff inside of it. Well, how do I align it by the baseline? Well, I can override another method on UIView and NSView, called viewForBaselineLayout. I'm going to return the label that's internal to my custom view.
And now Interface Builder is showing me that this view now has a baseline running right through the baseline of my label and if I delete the centering contraint on my caption, I can just drag this thing around and you can see it snapping right to the baseline of that custom view that I just created entirely in code.
[ Applause ]
Now I can go ahead and finish this off by baseline aligning these to these two views. So that's just a little look into using live views and some of the things that you can use to make sure really cool views. I'm really looking forward to seeing what you guys do.
So, the four steps that you need to do to get your custom content showing up in Interface Builder: 1, create a framework. Why do you need to create a framework in the first place? The way that this feature works is that when you define a class as designable, Interface Builder is going to build your framework target.
It's going to launch a Helper process. It's going to dynamically load your framework into that Helper process and then interact with it. And this also helps keep you from the mistakes that -- at least that I make -- while writing code, which is something like a crash. That way you don't have to -- you can see what the error is without having to suffer from it. Secondly, you create a subclass of UIView either with Objective-C or with Swift.
Third, you mark it as Designable. And I wanted to say a quick note about Inspectable as well. While Designable is a feature of this Custom Views feature, you can use Inspectables without having a Designable class. You can add Inspectables to any of your classes that you interact with in Interface Builder, and we'll show you those properties in the Inspector.
And then, finally, you just hook up your custom view with the class that you just created. Live Views allows you to do all kinds of things: you can see your custom drawing, you can have custom geometry and interact with it... One that I didn't show you is you can also provide the alignment rect insets that are on both iOS and OS X. You can debug your views right in the canvas. And you can also use several mechanisms for interacting with your code in design-time. I showed you prepareForInterfaceBuilder, but another one is this target conditional, TARGET-INTERFACE-BUILDER.
And you can use this with #if to either opt code in or out of live views. So, for example, you might have some server connection code that you don't want to run when you're inside of Interface Builder. So you can just opt that out using this Target Conditional.
I also showed you some new Auto Layout features since last year. Now what we want to do is want to add iPhone Support to our application. My co-worker just had time for iPad support. And our goal is that we're going to use a single storyboard to do this.
and this is made possible because of a feature called Size Classes. Size Classes is a feature of iOS 8 and Xcode 6 that allows you to specify how your View Controller and your UI adapt as the available size for your View Controller changes. Let me tell you -- I'm going to walk you through an example.
Let's say you start out with some View Controller with some size and it grows to some new size. What's important here is not the point size of your View Controller either in the smaller or bigger configuration. What's important is the magnitude of the change, small versus big. This magnitude is called a Size Class. A Size Class can have one of two values. Compact (think small) or Regular (think bigger). At any given time, a View Controller is going to have two Size Classes, one horizontally and one vertically, making the total number of combinations four.
So let's look at a concrete example. So I have our UI here and when we're in landscape on the iPhone, I'd really like that bottom bar to tighten up a little bit, to make more room for those images. So what we can do is in the configurations of our four configurations, for whether that bar or whether the View Controller is in a more compact vertical environment, we can just set that constant to 30 and in the bigger ones we can set it to 52. We're all good, right? Well, kind of.
If you notice, I have to specify the value twice. And this is going to make it really hard to make edits in the future. It's going to make it hard to maintain my app because every time I make a change I've got to make it in two places.
So Interface Builder exposes a third value in the Size Class called Any. And Any is simply, as its name suggests, either of the size classes. So I can say that I want that 30 to be for any horizontal class. I don't care what the width is. All I care is about the height, which is compact.
What about this 52? Well, I could also put it in Any for regular, but where I really want to put it is in Any Any. This is the default configuration. This says that it doesn't matter which device or which orientation or what the size of my View controller is, I want to use these values. And this brings up a really important strategy as you're designing your applications.
You want to do as much work in Any Any as possible. And then you just branch out to those more specific configurations as needed. And this is going to make your app much more maintainable and much more adaptable. Now this grid is going to become really familiar because this is actually exactly how we expose switching between the different configurations inside of Xcode. And let me show you how that works. All right.
So we're back in our lovely storyboard here. And the first thing I'm going to do in this storyboard is I'm going to enable Size Classes. So let me go ahead and open up the Document Inspector here and check Size Classes. Now two things are going to happen. One, if your document isn't using Auto Layout, we're going to turn on Auto Layout for you.
And them, secondly, it's going to upgrade all of your segues to the new Adaptive Segues. Now, I'm going to talk about that in a little bit. So we're going to enable Size Classes and immediately we're seeing the result, the designing, and this great, flexible, adaptable environment. Our View Controllers are showing a square to help reinforce that you're not designing for any specific, particular device, but rather for the particular size or magnitude of size of your View Controller.
So, the first thing that we want to do is we want to take that bar and make it a little bit narrower or shorter when our height is a little narrower. So I can just go ahead and put the canvas into a configuration that allows me to do that. So this is the first thing with Size Classes is transitioning through the different configurations. It's really easy.
If I open up this control here in the bottom of the canvas, you can see it was that grid that we were seeing earlier. And this allows me to pick which configuration I'm editing. When I pick a configuration to edit, it's going to resize the View Controllers for that particular configuration to reflect that. And now, any edits that I make inside of this particular configuration will be customized for that configuration.
So let's go ahead and do that now for the constant -- the height constant -- on our bar. So I'm going to go ahead and select this. Now I could double-click to edit this constraint, but instead what I'm going to do is I'm going to open the Size Inspector.
And you can see here all the constraints for my bar. Well, I really just want to see the ones that are being defined by my parent to kind of position and size this. I'm just going to filter the constraints down to those. And furthermore, I'm just going to look at size constraints. Then, to change the constant, just click once, type in 30, hit Return, and now I've customized my bar for Any, Compact.
[ Applause ]
You can see the result of that if I switch back to "Any Any" here. And you can see that bar grew back to that taller height. So, really, really easy to make customizations between configurations. Now the second thing about Size Classes that I wanted to say is, well, what's customizable between configurations.
There are four things that are customizable between configurations. One: I can change a constraint constant. Two: I can change a font. Three: I can change whole sets of constraints -- I can turn off an entire set of constraints (say, my Portrait constraints) and turn on a whole other set (say, my Landscape constraints).
And then, fourth, I can also customize subviews, turning them on and off. And this is different from hidden. When a view is just hidden, it's still participating in layout. But when I uninstall the constraint using the view using Size Classes, it actually takes it out of the View hierarchy so I can have new sets of constraints. So let's see an example of that now. When I don't have a lot of horizontal space, I want to turn off this rating.
So I'm going to go ahead and put the canvas into Compact width. And I don't really care what height it is. It can, you know, be as tall or short as it needs to be. And you can see... oh wow, yeah, that looks pretty bad. So let's go ahead and turn that caption off. When I want to turn a subview off in a configuration it's really just as easy as turning off the constraints of that configuration and then turning the View off itself.
When I use the constraint commands over in this menu, they're going to apply, again, for just this configuration. So let's go ahead and just clear the constraints for this View, and now we can uninstall it from this configuration. I can do this using the Inspector on a per-view instance or a really quick shortcut for getting that done is just command-delete. And command-delete will just turn it off in this configuration. Delete will delete it in all of the configurations.
I also want to go ahead and remove this constraint. So I can just select the constraint, command-delete, and now I've turned it off. And now I can add new constraints for just this configuration. So I'd like to take this Rating View and align it horizontally in my container. And I'm going to use the new -- or not the new -- just the existing alignment popover here.
I'm going to choose Horizontal, Center, and Container. And I'm going to change one of this Update Frame's values. You might have been wondering what this is. This allows... when you're adding new constraints, the values that you're adding those constraints for might not be the actual values that are currently reflected in the canvas. For example, I want to add Center in my bottom bar but my View currently isn't centered in the bottom bar. So I can tell Interface Builder, hey, when you add these constraints, just go ahead and put the Views in those new locations.
And that's what these options allow me to do. All Frames is just -- it updates it for the whole View Controller. And "Items of New Constraints," this is helpful if you're in the middle of doing a lot of different constraint surgery and you just want to move one or two Views. What I'm going to do in this case, I'm going to do all the frames in my View Controller. And you can see it adds that constraint [whisking sound] and it slides that Rating View right on over.
And if we go back to Any Any, voila. We've customized our interface across two different configurations very, very easily. And let's see what this looks like at runtime. If I go ahead and run my application... There, it's showing up, and I can rotate it, and you can see that bar is automatically adjusting. And on iPhone, because it's Compact, you can see that that caption isn't showing.
Now one thing I haven't talked about or pointed out yet is maybe something that you guys are wondering and you're saying, hey, you had an iPad storyboard. Wait a second. I saw a Split View Controller in there. I saw that you had a Replace Segue. I saw that you had a Popover Segue.
How is that working on iPhone? With the new adaptive View Controller API in iOS 8, all the wonderful system classes that you've come to know and love work on both iPad and iPhone. And the way that it works is that they adapt their environment based upon that available size.
So, for example, our Split View Controller , instead of showing side-by-side (because the environment is more compact) it's actually going to just push my detail onto my master when I'm in a more compact environment like an iPhone. Similarly, with my Popover Segue, instead of being a popover on iPhone, it's been turned into a modal without me writing any code. And this has to do with those new Adaptive Segue types. So let's take a look at those now.
If I select this Popover Segue here and go over to the Attributes Inspector, you can see it's one of the new Present As Popover Segues. And this is one of the new Adaptive Segues. Let's take a look at what other Adaptive Segues we have. Show is a replacement, for example, for Push.
And what Show in Show Detail does is it looks at the context that you're in to decide what to do. So, for example, a Split View Controller in iPad: it's going to actually replace the Detail if you have a Show Detail. But on iPhone, it's going to push that Detail aside on to the Master.
Now what's really cool about this is that this is accomplished by using two new UIView Controller Selectors, Show View Controller and Show Detail View Controller. You can override these for custom containers and then you can design those containers in Interface Builder to set up your Segues and it's just going to work at runtime.
The other two types are Present Modally and Present As Popover. And these are using the Present View Controller API instead of Present Modal View Controller which allows you to take advantage of the new Presentation Controller API which is a new object when you use Present View Controller. And you can do things like make sure that the custom transitions that you have are all coordinated along with the animations which is really, really great. So we're going to use Present As Popover which will allow our Presentation View Controller to automatically adapt.
Now if I go back to my storyboard here, you can see there's no button for closing this. And so, if I had time, I could go ahead and add this, and you're welcome to come down to the labs and I'll show you how to do this. But with the new Adaptive View Controller API, what I can do is I can take advantage of some of the overrides in delicate methods to do things like, for example in this case, I can say, when this Popover Segue gets fired, go ahead and wrap the View Control that you're presenting in a Navigation Controller, add a bar item, and then just on iPhone it's going to show me a Done button that I can use to close that Modal View Controller. But when on iPad, and it's showing as a Popover, well, I don't need that, so it won't show it. Very, very cool for being able to create great apps between both iPhone and iPad.
So we just talked about Size Classes. And, again, Size Classes is a really great technology that will make it really easy for you guys to create these experiences both for iPhone and iPad all within the same storyboard. And I also talked to you about the new Adaptive Segue Types. And we really want you guys to use these new Adaptive Segue Types because it's going to make your application be able to (hence, as their name suggests) adapt very easily between the different types of environments that it might run in.
I also pointed out that you can create custom containers and use those Show and Show Detail View Controller methods to customize exactly how those View Controllers are going to get presented. Maybe you have a Sliding View Controller or something like that, and you can build all that now within Interface Builder. What I want to do now is have my colleague, Quinn, come up. He's going to show you even more stuff that's new in Interface Builder and hopefully tell some better jokes than I did. Quinn?
[ Applause ]
Thank you. Hi. Thank you, Kevin. So my name is Quinn Taylor. I'm also an Engineer on the Interface Builder Team. This is such a fantastic team and I hope you can feel how much hard work we've done to bring to you guys. We love these new features and I can't wait to tell you about a few more of them.
So, first off, I want to talk to you about Asset Catalogs. We introduced Asset Catalogs last year with Xcode 5. And they're a fantastic way to manage resources inside your application, both for iOS and for OS X. And one of the first new features that we've added to Asset Catalogs in Xcode 6 is support for Size Classes.
As Kevin has just been demonstrating to you, you can easily adapt your user interface for Compact or Regular height or width. And now notice that we have new fields in the Inspector when you selected an image in your Asset Catalog that allow you to customize the same way.
Now if you select one of these -- for example, we'll customize on Compact width. You'll see that new rows appear that allow me to optionally specify new images that will be used if I'm in a Compact width scenario. So, any images that you don't actually specify for a specific configuration will be inherited from a less specific configuration, just as Kevin was talking about with Any Any. So this is a fantastic feature to allow you to customize.
Second, Alignment support. So, there may be occasions where you have an image provided to you by a designer that doesn't fill the entire space of the image. For example, it may have a glow effect, some other padding that causes it to be inset. And now you can also show that information and convey that inside of Interface Builder and your Asset Catalogs.
And this will correspond to the alignmentRect properties on either NSImage or UIImage when you can specify alignments from any of the four edges. This is fantastic. And next is Image Formats. So when we launched the Asset Catalogs last year, we supported PNG images. So we've heard your requests. The first thing we added is support for JPEG images [applause].
- Whoo.
- Some of you love your JPEG images. This can be really handy when you have resources that might be large and compress better with JPEG than they do with PNG, so you can save space in your application, and that's great. Second is PDF vector images, and these are great as well.
So this is -- let me tell you, this is a fantastic way to specify an image that will scale automatically to your different scales and resolutions. When you're building an Asset Catalog for iOS, those vector images we've rasterized to the correct resolutions and scales at build time. On OS X, however, they're preserved at runtime and they'll even appear at scale for printing which is a really cool bonus.
And you're also able to mix and match bitmap and vector images for any particular asset. And last is support for template images. Matthew mentioned this a bit on Monday. Template images allow an image to be treated kind of as a stencil in your application so you get kind of an outline effect.
And traditionally this is done by detecting whether the file name ends in "Template." And now we give you the ability to override this default behavior directly in Interface Builder in your Asset Catalogs. So, that's it for Asset Catalogs. Next, you've seen a few new classes. I'm going to talk about OS X for minute. NSVisualEffectView is a brand new class in OS X Yosemite.
You've seen it pervasively throughout the system behind Notification Center, behind your menus and behind your source lists and so on. You'll see effects like blurring, translucency, vibrancy, punch-through effects, and masking. And you can bring these same effects to your own applications. VisualEffectView is supported completely in Interface Builder. And you can have your own custom views participate in vibrancy effects by overriding the allowsVibrancy method on NSView or UIView. For much more information about how to integrate this, definitely check out this session on Adopting New Features of the UI in Yosemite on video.
Next, you've heard word of a new System Font. Andrea's talked about this. The great news is for you, you don't have to do anything. Use the system font; it's going to work. AppKit and Xcode will take care of you, so you don't have any worries on that front. Speaking of fonts, iOS Custom Fonts... [applause] [Laughs] You're already excited.
I share your enthusiasm. For a couple of releases now, you've been able to use Custom Fonts in your iOS Applications. You can put them in your project and copy them to your bundle. And now we're adding support for being able to pick those fonts directly in Interface Builder and have them show up in the canvas live for you. So here I've chosen this font that looked pretty cool in OS X, brought it over, and I can see, I can ingest the metrics and make sure that it looks just right without having to run my application over and over. This is a fantastic timesaver.
All right. So pictures are worth a thousand words. I feel that demos are worth a thousand pictures. You know, I'm going to, I'm going to get in a -- step on Kevin's toes just a little bit here with this custom font. So I've got my iOS storyboard that he's been working on.
And, you know, this looks fantastic. He's done such an awesome job. But, you know, the thing is, this is a vacation app. And to make it, you know, make it a little bit more fun and vacationey, maybe we just need a custom font. Now I've actually snuck a font into his project here.
So I'm going to go right over to the Font Picker, and you'll see that it shows right up in here in Interface Builder, and I can pick my font. It shows right up. Now that looks a little bit smaller than what I was expecting, so maybe I can bump up the size just a little bit to 36. That looks pretty good. And I could do the same thing here for my subtitle, my label.
Hmm. Bump the size up to -- 20 looks pretty good. Okay. And now, since those fonts are just a little bit different in metrics, I can update those frames. Okay. So that looks fantastic. So now I can see right on the canvas what it's going to look like at runtime. I've got that information available to me. And it's going to save a lot of time when you're designing your iOS Applications.
All right. So now I'm going to jump over to what I've been working on while Kevin was onstage. I was working on the Mac version of this. He's a pretty quick worker, so I was trying to catch up with him. I've kind of copied some of his work here, you can see. So we've got a very similar layout.
And what you'll notice is I'm using OS X Storyboards which is a new feature in OS X Yosemite. And, if you're familiar with storyboards, this will be immediately comfortable to you. We're building up our interface using Scenes connected with Segues. And we're showing our organization directly here in the canvas, all the connections between them, and how my application's going to flow.
And this can be an incredibly convenient way to see how your application works. You'll notice that my main menu is actually still present here and I can edit that just as I would in .XIB Files. You can actually do your entire application development within an OS X Storyboard.
So, in addition to just being familiar to iOS developers, there's some great features within storyboards that actually make your life a lot easier, you Mac developers. For example, presenting a Popover or a Sheet can be rather difficult. And you have to write code to get it to start and end. And this is just as simple as creating a Segue to present a Popover. You have a scene that has your view, and voila, it's right there. It's a really fast way to do it.
In addition, managing Tab and Split Views. Here, in fact, we have a Split View Controller. Now NSSplitViewController and NSTabViewController are also new in Yosemite. And you can use those in either XIBs or Storyboards. So I've configured a Split View Controller here with two Split View items with my Master and my Detail, similar as what I would do on iPad. And you can see I can use the same type of things here. I've got, in fact, an NSVisualEffectView down at the bottom. And it just works. So let me show you, running this application, on Mac using storyboards.
Okay. So here's my application. I've got a nice looking source list and I can click between them. I've got my photos, I've got my rating at the bottom, I've got my captions. And I've done it with Storyboards. I can see all of it in one place and it's incredibly convenient. So I hope you guys will check this out as you're working on Yosemite and higher. These can be deployed only to Yosemite and above. But they are a fantastic way for new application development to speed up your development. All right.
Next I want to talk to you a little bit about gesture recognizers. You're probably also familiar with these from iOS. Now in Yosemite we've added five gesture recognizers and we have support for them in Interface Builder as well. So let's say that I want to add a gesture recognizer. I'll filter an Object Library. You can see these five that pop up. Let's say that I want to go ahead and put in a magnification gesture recognizer. I want to do some sort of pinch-to-zoom kind of action.
So it's as simple as dragging it from the Object Library onto the view where you want to recognize the events. Drop it right there. You'll see it appears in my Document Outline here on the left. Okay? Now all I have to do is connect it up to the source code. So I have my View Controller here. I'm going to Option-Click on my Site View Controller to open it in a split. And let me close this area for now.
I can use the ConnectToSource feature within Interface Builder. I can control-click and drag from my magnification gesture recognizer directly into my source code and have it create an outlet or an action for me. In this case, I want to create an action method that my gesture recognizer will invoke when events happen. So I'm going to select Action and try to be a little clever here.
I like to use fun names sometimes, so I'm going to call this "Biggify." Add some mystique and excitement to the code. All right. So now you can see I've got this connection right here to the action method, right, for my gesture recognizer. And when I run this, this method's going to be invoked and the code that I write here will be fired without me having to do any event detection myself. It's a fantastically convenient way to develop your applications.
Okay. You know I'm already kind of starting to regret the choice of that selector name, "Biggify." It's a -- you know, when my co-worker comes back from vacation -- look at how happy he is there on vacation while we're at WWDC. And you know, he's not going to be too pleased to find a name like "Biggify." So we're going to use the new Find and Replace feature. And I'm going to use command-option-shift-F to bring up my Find Navigator in the Find and Replace mode.
So I'm going to get that horrible selector name out of here. I'm going to search for "Biggify" and... something more reasonable, like "Zoom." And as I hit return, you'll see that it detects now instances of that selector, both in my source code and in my Interface Builder documents. They're a fantastic timesaver.
[ Applause ]
So I can select both of these instances and replace them. Oh, see -- Snapshots is trying to get in on my photo application here. It wants to take a picture, too. So we're going to actually just replace that. And you can see I've got Zoom right here for my Magnification Gesture Recognizer. The action has been replaced as Zoom. I don't have to destroy my connection, change my selector name, and recreate all those connections that may call into it. So it's a fantastic timesaver for Find and Replace.
In fact, Find and Replace also works within Document Find. So, with command-F, I can bring it up right inside of my document here and I can search for all sorts of things. You can find strings that appear in text. If I look for a label, I can find those as well.
And it will highlight for me where it may appear in a Selector Name, where it may appear in text in a string, and so on. For example, let's look for -- another thing that you can use, to find for (unexpectedly convenient) is to jump between parts of your view, if you like.
So, for example, I have my Site View Control and I have a list you can draw. So I can type List, and it's going to show me -- here's my Site List Table View Controller. This can be incredibly handy when you have a large storyboard and you have your scenes named appropriately, and you can jump between them with Find right in the document. So this is a fantastic timesaver as well.
So the last thing that I'd like to demonstrate for you is a little bit of how Interface Builder participates in your localization workflow to help improve that. So I'm going to open my Assistant Editor again, and I'm going to close my utility area. Now I want to bring up my Preview.
And you'll see that my Selected View shows up in the Preview on the right side. Now if I have localizations already, I can use those to preview. Kevin and I have only been working on this for a little bit. But we're pretty sure this app is going to take off worldwide and we're going to have all sorts of localizations. For now, all we have is English.
But even when you don't have any translations, you'll see this entry in there, Double Length Pseudo-Language. So I can test this and see: "How is my user interface going to react? Are my auto-layout constraints set up correctly to help those views?" You can go ahead and clap, yeah. That's fantastic.
[ Applause ]
I can see without running my application how my interface is going to react. And I can see that as I select from view to view. All my strings will be doubled and I can easily see that. Once you have translations, you can easily plug those in as well and you can test those in Interface Builder at design time which is a fantastic timesaver.
All right. So, you've seen some of the great new features that we've been working hard to bring to you this year in Interface Builder and Xcode 6. Again, revisiting these three big themes: First is Liveness, that more of your views and your content and your application are live in the IB design canvas than ever before. There's more power for you to iterate quickly and avoid the costly build and run and debug loops. Second is Adaptability and greater dynamism. Being able to adapt to changes in configuration where your view can appear.
And third is Power & Parity. Great new features in OS X and iOS and within Interface Builder itself to help you work more quickly and efficiently than ever before. Any questions you have should be directed to our Developer Evangelist, Dave Delong. We have great documentation online available. There are quite a few related sessions that will be fantastic for deeper dives into the subject matter that you can catch on video. Thank you so much and enjoy the rest of the conference.
[ Applause ]