Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2009-409
$eventId
ID of event: wwdc2009
$eventContentId
ID of session without event part: 409
$eventShortId
Shortened ID of event: wwdc09
$year
Year of session: 2009
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2009] [Session 409] Getting Sta...

WWDC09 • Session 409

Getting Started with Interface Builder

iPhone • 47:34

Interface Builder lets you rapidly design your application's user interface on Mac and iPhone. Jump-start your next application by learning how to integrate Interface Builder into your Xcode workflow, connect your code to your interface elements, and visually design your application's interface. Build a strong set of skills that will help you create quality applications quickly and easily.

Speakers: Joey Hagedorn, Kelly Keenan

Unlisted on Apple Developer site

Downloads from Apple

SD Video (167.5 MB)

Transcript

This transcript has potential transcription errors. We are working on an improved version.

Good morning, and welcome to Getting Started With Interface Builder. My name is Joey Hagedorn and I'm an Engineer on the Interface Builder team. And today we're going to talk about building applications with Interface Builder for Mac OS X and the iPhone. There's three main things we need to talk about today. First, laying out your application inside Interface Builder.

And that's putting all the views and controls into your application, and then configuring them such that they look and behave the way you want them to. Next, we'll talk about connecting that interface that we build to the code that you write so your application does something interesting. And this consists of if you want to make a button call some method, or if you want after a user does an action you need to update the interface. And finally, we're going to talk about the life cycle of a nib.

What's File's Owner, and how does your view get on screen? So to talk about the first part, the easiest thing to do is just build a simple sample application. This is the application we're going to build today. It's got a big map in the center from the new MapKit framework. Some buttons along the bottom that take us to a couple of predefined locations on the map.

And across the top, there's a latitude, longitude coordinate on the center of the map. So let's get started. OK. So I've got Xcode open here and I'll create a new project. I'm going to choose a view-based application because we just have one screen full of information to display. Just save it on the Desktop.

[ Silence ]

And I'll resize the window here. OK. So before we get started building the application, I want to add a couple of resources to the project. The images for the buttons that we'll have along the bottom. So I'm going to down to my Downloads folder and grab our images and just drag them into the Resources group to keep the project organized.

Click Add. And also, because we'll be using the MapKit framework today, I'm going to add that framework to the target. So to do that I'm going to the target's group in the Groups and Files area. And I'm going to hold down Control and click on the Applications Target, and choose Add and Existing Framework to pick MapKit and that's all set.

Now, I'd like to review a couple of files that came in the template. If we look in the classes group, we see there's the Application Delegate, Header and Implementation file. And that contains some code for now that'll get run when the application is launched. And also the PlaceMapViewController. When the application launches it'll ask ViewController for its view to put it on the screen. And that ViewController is going to get its view from inside the User Interface file, PlaceMapViewController.zib. So I'll double-click that now to open Interface Builder.

[ Silence ]

And what we see showed up on the screen is this Document window and this is a representation of what was contained inside that file. I'd like to draw your attention to the View icon, which is the main view that we'll be presenting. And this view, it's already open but if we double-click it, it brings forward the Editor window, which is. That's the view we want to put stuff in.

So let's get started and start adding elements to the interface. To get. To put elements on the screen we go over to the library on the left-hand side of the screen, and this contains different objects that we use in Cocoa Touch. If we were building a Mac OS X application, we would see the objects that would be available to put in an OS X view. There's a couple of different ways we can view the things in the library.

As I go down to this Action menu in the lower left-hand corner, I can choose to view as icons for a more condensed view. Or as small icons. But for now, I'll just view in the default layout. And I want to put a navigation bar at the top, so I can click in this filter field and just type nav.

It'll filter down and I just grab a navigation bar and drop it in the top of our view. OK. So we've started building our interface. But this navigation bar has the default blue style, and we want it to look black. So we click on it and bring our attention to the Attributes Inspector on the right side of the screen.

We want to change the style to black opaque. There's some other things about the Inspector while I'm here. If I put my mouse over a given control on the Inspector, it brings up a tool tip. And the tool tip not only displays a description of what that control does. But it also shows you the API that's related to that control. So you can correlate what you're doing in Interface Builder to what you might see in other documentation or in other codes somewhere.

There's a whole number of controls we can. Or options to edit on this view. But we only need to change it to black for now. We should also get a nice placeholder title, so I'll just select it in the Editor view and double-click it. And I can edit it right in place.

[ Silence ]

OK. So that looks good. Now, I want to drag the toolbar to the bottom, so again I'll go back to the library. Go to the filter field. Tool for Toolbar. And I'll drag that out. And as I bring it into the window, you'll notice, Interface Builder sees that we already have a black styled navigation bar, so it tries to help set up some properties that we think might be appropriate.

So it noticed the changes to the black style. Also, as I drag it towards the bottom of the window it sort of clicks into place because that's where toolbars go and the guides are helping us out. One more thing, as I drag objects around you might notice these blue dashed lines.

The blue dashed lines are Interface Builder's HI guides and they give us, if we were positioning buttons for example, they would help position them such that they adhere to the user interface guidelines. So they can really help ease development. You don't have to go look that stuff up sometimes. Especially helpful for putting buttons in a dialogue or something like that. So let's add another button to the toolbar.

Go back to the library. Just drag that out. And the way UI toolbars work is they arrange their contents from left to right. The framework does this for us. So if we want to have a button on either side of the screen, we need to add a flexible space in between them that will grow to fill the available space. So I just grab one of those from the library and it shows up as this dashed line. And that's only in Interface Builder. When it runs, there'll be nothing there.

It'll just be the space. OK. So that's looking good. But we're still missing the main part of our interface, which is that big map. So to do that I'll go back to the library one more time and clear the filter field and find the map, and I'll just drag that in. Again, Interface Builder is trying to help with this. It resized it to be.

To fit the available space between the navigation bar and the toolbar, so I'll just drop that into place. While I'm talking about size, I'd like to bring your attention to the Size Inspector to do more things with size. So we go over to the Inspector on the right-hand side of the screen and click on the Ruler icon. And now we see properties related to the size. We can adjust the width or height numerically, if that's helpful.

And there's also a section on autosizing. What autosizing is in Cocoa and Cocoa Touch, when a super view is resized we need to tell the subview how it should change relative to that. So it might grow with it. It might stay pinned to a certain side. So let's explore the autosizing controls to see how they work. I'll select the Toolbar, and if I move my mouse over the autosizing area, we'll see it animates and gives us an example of what'll happen. You can see that as the super view changes size, the toolbar grows with the width of its contained view.

But it stays pinned to the bottom and left and right. So on the iPhone, when does the super view change size? It's not like you're going to resize the window. The screens affect size. Well, that happens when you're rotating the view. So it's important to set up autosizing on the iPhone as well as on the Desktop. So I'll explain this control also. Inside the box, there are arrows that indicate that the view will grow with its super view.

So if I disable this spring, as we call them, you can see now in the animation that it's not going to resize with the width of its super view. To see how this looks when the device rotates, I'll go to the top of the window and click this small arrow and we'll simulate a rotation. And we see that the toolbar doesn't really look right anymore because it has the wrong configuration. So I can fix this. I can select it.

Drag it to the width of the view and turn that back on. Now, around the outside of the control we see these I-Beam figures. If I disabled the one on the bottom and enabled the one on the top, that indicates that it'll stay a constant distance from the top of the screen rather than the bottom of the screen. So now, if I rotate back to a portrait orientation, we'll see that the toolbar did what it said it would, but this is probably not a desirable configuration. So to fix it I'll go back to Landscape, select the Toolbar, and pin it to the bottom.

Rotate and it's looking all right now. There's one more thing I wanted to do to configure the map though, so I'll click on it, go back to the Attributes Inspector, which is on the right side, the first tab. And I'd like it to display satellite imagery as well as the road imagery.

So I can just change the type to hybrid instead of map. So our interface is coming along. It's at the general layout. But we should add those images for the buttons. The first thing I'll want to do is change their style from bordered to plain. So to do that I'll click the.

Select the Toolbar and then I'll click again to select the button. Hold down Shift, and select the other button as well, because I'd like to add it to both of them. And I can edit more than one thing of the same type with Interface Builder's Inspectors. I'll go up to the Style of the Bar Button Item and change it to plain.

Now the borders went away. But I need the images still. To get those I'll go back to the library on the left side of the screen and choose the Media tab at the top. The contents of this tab are populated automatically with the images and media in your project. So as long as the file is associated with your project you'll see the images you need.

I'm going to grab this Globe icon and put it on the left button, and I just drag it and drop it into the button. And for the right button, which is the San Francisco button, I'll grab the Golden Gate Bridge for an icon there. So our view looks pretty good right now. I'm going to go ahead and save this, File and Save, and switch back to Xcode.

Now that I'm in Xcode, I can build and run and try it out. OK. So we've got our interface that looks OK. It looks fine, but there's. The buttons still don't do anything and. But we've made a pretty good start. So let's talk about what we did for a little bit.

[ Silence ]

So we didn't do this. We didn't write a lot of code. But so what this is, is this is the whole implementation of the application we're writing today without using Interface Builder. It includes a lot of extra code. Stuff like creating and configuring the UI. When I just dragged out the toolbar and added the buttons to it, that's all I had to do.

That code we never had to write. Interface Builder isn't generating it for us either. It's just not in our program anymore. There's also a big section of code that's devoted to just positioning the different views on the screen. That's also code we didn't have to write. Now, there still is important code here and that's to make the buttons do things when we click on them.

And to talk about bringing some more life to your interface I'd like to introduce Kelly Keenan to talk about connections.

So I'd like to talk you about how to make this project actually do something. So Joey started by giving us a user interface that we can use. A view of our map and our buttons and our title.

And now we need to make that actually do something. And as you know, the place where you do that is in your code normally. So let's talk about how to interact between your code and your views, and that's going to be the interaction between Interface Builder and Xcode, the project with all your important code in it.

And the way we're going to integrate with Xcode is by going through the Document window in Interface Builder. We're going to use the Document window and pieces of it in order to access the code that we've written in Xcode. And we do that. In the example that we're using today, we're going to do that through File's Owner.

File's Owner is going to represent the ViewController that we have in Xcode. And that header code is going to look like this, OK? And we want to make sure that we can connect our buttons to the actions that we write, the methods that we write in our project in Xcode. And to do that we have these two methods here, zoomIn and zoomOut. And you can see that there's a keyword in there called IBAction.

Now, Interface Builder has access to all of the code in your Xcode project. But you don't necessarily want to see every method that you write and every instance variable that you write. So IBAction is a way to say to Interface Builder that this is the method that I care, that I need to be able to access from MyViews.

And if you ever want to look up the definition of IBAction is actually just void. So when this is compiled it gets turned into void, so it's nothing that changes your code when it's finished. It's just for Interface Builder to know about it. In the same way that we do actions to connect methods, we're going to use IBOutlet as a keyword to tell Interface Builder what instance variables we're interested in.

And what properties we're interested in. In this example here, we're going to connect our map and our navigation bar, because we need to do something with them in code. So we used the IBOutlet keyword to let Interface Builder know that this is something that we're going to be using. Now, since we're using Properties I just want to remind you that when we retain something we need to release it. So if I forget to do that, make sure you tell me.

So let's go ahead and look at the demo. We have the view set up already that Joey made, and we have these buttons that we would like to connect to something. And I showed you a little sample already that I want to be able to connect them to those action methods that we have. The zoomIn and zoomOut methods.

So let's go ahead and go to our Xcode project. Now, the template that we use set up a class for us already. The class. The PlaceMapViewController. Try to say that fast a few times. The PlaceMapViewController is going to be the controller that manages our PlaceMapView that we have in Interface Builder. As you know, this is all part of the model view controller paradigm, and this is the controller part, whereas the view we made in Interface Builder is that view. So the first thing we'd like to do is we'd like to have that zoomIn and zoomOut method.

So I'm going to add it here in our ViewController. And notice that I've used the IBAction keyword for both of them. Great. So we have the zoomIn and zoomOut methods declared, but we have no definition. We need to actually make them do something. So let's go to the implementation file. For the purposes of our demo today, I'm going to delete everything that's in here at the moment and we'll start from scratch. And let's put in the zoomIn and zoomOut method. So these two methods do practically the same thing.

The first thing they do is create a home coordinate, and luckily, I've already determined what the locations are that I need for my demo today, so we're going to use those. Using the home coordinate we're going to create a home region, and this is all part of the MapKit framework that we added earlier. And feel free to look up the documentation for that later. I had to. It's not something I knew off the top of my head. So we use the home region to set the region of the map.

It's great. I have this map property here that I haven't made yet. We need to be able to access the map from our code so that we can change it and so the region to the coordinates that I've specified here. So let's go back to the header file and add a map property.

And before I do that I'm going to make sure that I import the MapKit. So let's add an instance variable for our MapView. And I'm going to add a property for it. And notice here that I've used the IBOutlet keywords so that Interface Builder knows about it. Great. Since I've added a property, I also want to go to the implementation file and make sure I synthesize that property.

And the one thing I asked you to remind me to do is that I retain that property, so I also need to release it. So in our dealloc method I released the map and then called dealloc on super. OK. So now, I have. In the header file, I have a map and I have two methods that I want to connect to MyView in Interface Builder. So let's go back to Interface Builder.

I'm going to hide this for a minute. OK. So back in Interface Builder I need to be able to make those connections between my methods and instance variables. So in this case, File's Owner is going to represent that controller code that we wrote. And to make that happen I select File's Owner and I go to the Identity Inspector in the attributes. In the Inspector, sorry. Go to the Identity Inspector and you'll notice that at the top we set the class identity. And in this case, the template has already set it for us, so this is set to the PlaceMapViewController.

OK? Great. So File's Owner is a representation of our controller that we just wrote which has that instance variable and it has the methods. So now, I want to make those connections. So to make those connections I'm going to Control-click on File's Owner. Again, I Control-click or right click on File's Owner.

And now I can see a list of all the outlets and actions that are available in my controller. So the first thing I want to do here is I'd like to connect the map to the map in MyView. So I just drag from the well on the right-hand side to my MapView. And it might be difficult to see, but nothing else highlights here except for the MapView. Interface Builder does a little bit to type check to see what exactly will connect to this map.

And we already said that the map was an MKMapView, and here we have an MKMapView. So we select that, and now you can see in the Connections head that we've connected the MapOutlet to the MapView. And now I want to connect to these two actions, zoomIn and zoomOut. So to make those connections I'm actually going to show you a different way that we can make connections. So there's two ways, and depending on which way is more comfortable for you, you might choose to do the first way or the second way.

So in this case I'm going to use Control-drag instead of Control-click. So I'm going to select the button, and in this case, I want the zoomOut button, and I'm going to Control-click and drag from the button to File's Owner. And now I get a list of the actions that I can connect that button to.

So I'm going to connect it to zoomOut. And again, with the other button I'm going to select my zoomIn button and Control-click and drag from the button to File's Owner. I can see the zoomOut there's a dash next to it, meaning that it's already connected to something, which is fine, because I wanted to connect this button to zoomIn, so let's select zoomIn.

Great. So now if I Control-click again on File's Owner, I can see that the zoomIn and zoomOut actions are now connected as well as our map. Now, another thing you might notice in here is that there is an outlet that was already connected for me, and that was done by the template for us.

And that's the ViewOutlet. So our PlaceMapViewController is actually a subclass of UIViewController. And just like we added an instance variable map to our controller code, UIViewController has a ViewOutlet that we need to make sure it's connected as well. And in this case the template has already done that and made sure that we connected the ViewOutlet to the view. So File's Owner is a representation of our PlaceMapViewController. Great. Now, when exactly does this ViewController object get created? To look at that I'm going to go back into the Xcode project and there is another zib file here, the Main Window zib. And if I open that up.

[ Silence ]

And look at the Main Window zib, we'll see it also has a view con. It also has a File's Owner. And if I select that we'll see that its class is set to UIApplication. This Main Window zib is going to be the window that gets launched when our application starts to run.

Now, inside of the zib we have a PlaceMapViewController. And when I selected that you can see that the class is set to PlaceMapViewController. This is where MyViewController is actually being created. So when the Main Window zib loads it will create a PlaceMapViewController. We've set the PlaceMapViewController to the other zib, the PlaceMapViewController zib.

And so when one of these is created it needs to open up the other zib and load that view. And we can see that that happens in the PlaceMapAppDelegate. In this case the view is loaded when we add the controller's view to the window. So the window is open and created. It creates a controller, and the first time that the ViewController accesses the view is when our other nib gets loaded and everything in it gets created.

OK? So we've made connections and we have seen how things are connected and what's going to create what. So let's build and run and make sure that those buttons actually worked. OK. So hopefully if I did everything right, if I click on the zoomIn button that represents San Francisco.

It did nothing. And the question here is what did I forget to do? Well, luckily I'm pretty sure that what I forgot to do was save the file because everybody has to do something wrong in their demo, right? So let's try this again. Build and run. Stop the executable that's running and try it again. Ready. Set. You guys believe it'll work this time?

[Audience] Yes.

Are you sure?

Heck, yes.

I'm not so sure. OK. I'm going to try. Oh, thank goodness.

Yay! OK. Does that place look familiar?

[Inaudible].

Yes. It's where we are. Surprise! ZoomOut hopefully does what it expects to do. It zooms out. Great. So we connected two buttons. Woohoo! OK. Now, the thing we didn't do yet is set the latitude and longitude, OK? We have those. Joey put in a placeholder text for us and expected me to make stuff happen. So we need to set the latitude and longitude string in the navigation bar.

So to do that let's go back to our ViewController which we said is what manages our view. And in our ViewController we want to be able to access that navigation bar so that we can change its title. So I need another instance variable here and that's going to be a UINavigationBar. This way I can make the same kind of connection and access this as well as the map. I'm also going to make it a property, and since I've done that let's save the header and go to the implementation file and make sure I synthesize it.

And don't forget, I should release it. So great. We have a navigation bar instance variable that we can access. Now, we need to actually do something. So I'm going to make a method called updateString. And I'm trying to remember right now. Yes. I'm just going to add my method right here. Great. OK. So I have this updateString method.

It's going to take one parameter, a region. It's going to use that region to set a string to the latitude and longitude of the map. And we're going to take that locationString and use it to set the title of the top item of the navigation bar. OK. So that may be a little confusing and that's because usually navigation bars are used to navigate through different screens of information. And to learn more about that I highly recommend you stay for the next session.

But for now I'm just going to use it to make a title for my application. So again, I set the title of the top item of my navigation bar. And great. So I never called this method anywhere. That's kind of a problem. So I need to update the locationString any time my map changes.

So in order to do that I need to know when the map changes. So the map has. The MapView has a Delegate Method. Now, a Delegate Method will. I can set my controller to be a delegate of the MapView. And if I implement this Delegate Method then any time the MapView changes it's going to tell its delegate, in this case my PlaceMapViewController, that it changed.

And it's going to call this method mapView regionDidChangeAnimated. And that's going to allow me to do something when the map changes. In this case, I am going to update the locationString when the map changes to the MapView's new region. Great. So now I have a place where my locationString is actually updated.

So let's save that and go back to Interface Builder. And just to clean things up I'm going to close that main window because we don't need to look at that anymore. And I need to make some connections. The first one is that if I Control-click again on File's Owner I will get the Connections display.

And I've added a navigation bar in here so I can make the connection from the navigation bar to File's Owner. So I've made that connection. So now in my controller code I can actually access that navigation bar. Now, the other thing I need to do is if I control.

If I select the MapView and Control-click on it I actually have an outlet in here for MapView called Delegate. So we need that Delegate Method, but we need the MapView to know it has a delegate because it doesn't know that the ViewController wants to be its delegate right now. And so I can drag from the MapView's delegate to File's Owner to say myViewController is going to be the Delegate for the MapView. Great. I've made those connections. And before I forget, I'm going to save so that I don't get embarrassed again by not having things work.

And let's bring up Xcode again.

[ Silence ]

There is one more thing I want to do before I run my application. And the thing is that when my MapView loads right now it's going to have latitude and longitude still up there until the map changes. And so I need a place where I can make some. Do some custom changes before the user actually sees MyViews. This is where it becomes important to know that the.

Our ViewController has a method that we can use called viewDidLoad. And now what this does is gives us a chance after the super calls viewDidLoad to write our own custom code to do something before the user sees the view as it's loaded. And in this case I want to update the locationString to whatever region the map defaults to. So now if I save this and build and run, when it launches you'll see the latitude and longitude has already been set. If I zoomIn, the string changes to the location of Moscone. And if I zoomOut it changes back.

And that concludes our demo.

[ Clapping ]

So Joey showed us this code, OK? And there's a couple more things that we can take out of here now. So one of the things that we can take out is we no longer have to set targets and actions. So we did this by making connections in Interface Builder between File's Owner and our buttons.

So this is code we will never have to write and never have to maintain. OK? The other thing is we looked at that Main Window zib file, and in the Main Window zib file we saw the ViewController and that it's being created there. So we no longer have to create that window or the controller, because they're being created by loading the zib files. So again, the more code that we will never have to write or maintain. And in the end, we managed to write 42% less code than by using Interface Builder.

This gives you an opportunity to focus writing code on the stuff that's important to you. The stuff that makes your application unique and different. So we've talked about creating views in Interface Builder. How to make connections to those views to your code in Xcode. And now I'd like to look at the life cycle of a nib.

[ Silence ]

And to do that let's ask a few questions of the nib. And the first is what object actually manages MyView? These are questions I ask myself in order to figure out how I'm going to write my program and put it all together. And we just learned that the object that manages your view is going to be a ViewController in the example that we showed. Yet other times it might be a different kind of controller, and that's up to you and your code and what you need it to do. With the example we showed today we had a zib with a view in it and we're using a ViewController to manage it.

So how do we link our view to the ViewController? And we did that through File's Owner. So our ViewController was the owner of this zib file with our view in it, and that gave us access to be able to make connections between the two So now. Great. I know that I can link my code to MyView, but what actually is happening when I save an Interface Builder file? But what's happening is all of those objects you dragged out of the library and used to create your user interface are real live objects. So they're real buttons, real scroll bars, real MapViews. They are going to be saved out to your zib files.

And that zib file you can df it so that you can see changes that you've made, but it's not something you ever want to edit or merge by hand. You always want to open it in Interface Builder. We add some extra information. This is our design time format, and we add some extra information so that Interface Builder knows some stuff about your zib file that doesn't need to be known at Runtime. So when you compile your project your zib file is turned into a nib file. And you might have heard I sometimes interchange nib and zib file.

Sorry for that. I, just to clarify. A zib file is your design time format. And a nib files is a Runtime format. So the nib file is going to be launched on your iPhone or on your Mac OS X app at Runtime. So when does the ViewController actually load MyView? Now, we briefly looked at this. And in our sample app this happened in the AppDelegate.

So what happens is the ViewController that we made as a subclass of UIViewController. And UIViewController, when we call View, which why I said it was important to make sure that that ViewOutlet was connected to the view in our zib file. The first time the ViewController accesses the view it says, Did I already load this view or not? And if it didn't load the view already, the ViewController is going to call loadView. Now, you don't want to call loadView yourself. Let the ViewController actually do this for you.

But the loadView method is actually calling a method called loadNibNamed and is passing the name and an owner and some options. And this is where the nib is actually being loaded. So the ViewController is loading the nib file for you. So the next question you ask is great, the ViewController is in charge of loading MyView.

But when do I get to configure MyView? And we showed an example of that, and that's in viewDidLoad. OK? So we let the super load do anything in its viewDidLoad method first. And then you can use this method to customize your view before the user actually sees it. So what happens when MyView is loaded? What's really going on here? Now, when we saved out our view, I said they're real objects. We never write code for these objects. They're live, actual objects that we've saved out.

So at Runtime they just get recreated. So we take that nib file, recreate the view. The window, the view, the navigation bar we used, the MapView that we used and the buttons and the toolbar at the bottom. These are recreated. The connections that we made are then made, so we're making the connections between those actions and outlets, the methods and instance variables that we had, to the buttons and the views. Those things are all hooked up for you. And then methods like viewDidLoad are called so that any customizations you need to do can then be done before the user sees the view.

So today we talked about how to create an interface by just dragging and dropping elements from Interface Builder into a design surface using real live objects that you can configure directly on the design surface, such as double-clicking the buttons. Or using the Inspectors to edit different properties of those objects. We then learned how to make connections between those views.

So how to connect the methods that we wrote in our code to the buttons that we made in our views. And the instance variables that we had in our code so that we could access the different views that we had such as the MapView and the navigation bar. And we looked at the life cycle of a nib.

What actually happens when your nib is saved and then run later. And if you'd like more information about Interface Builder, our Developer Tools Evangelist, Michael Jurewitz, can answer questions for you. But you can also find documentation for the Human Interface Guidelines or the Interface Builder User Guide online.