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: wwdc2002-904
$eventId
ID of event: wwdc2002
$eventContentId
ID of session without event part: 904
$eventShortId
Shortened ID of event: wwdc02
$year
Year of session: 2002
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC02 • Session 904

Using Interface Builder

Tools • 1:03:08

Interface Builder is Apple's premier Aqua user interface design tool for Cocoa and Carbon applications. Learn how Interface Builder allows developers to easily access underlying framework concepts like Cocoa targets and actions and the Carbon Event model. This session provides an overview of the basic features of Interface Builder and then goes in-depth on new capabilities.

Speakers: Henri Lamiraux, Isaac Wankerl

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Ladies and gentlemen, please welcome user experience evangelist, John Galenzi. Well, good afternoon. Welcome to the session about using Interface Builder. And Interface Builder is Apple's interface design tool of choice. If you're creating any UI in your application, it should be in this tool that you prototype it and then you begin to sort of lay it out and figure out what it's going to look like and how it's going to work and then use the results of that to integrate it within your product, whether it's Cocoa or Carbon.

And we'll talk a little bit about how to use the product in general, but then go into specifics about new features and how to integrate the product with what you're doing in more detail. So to do that, I'd like to introduce Monsieur Henri Lamiraux. Good afternoon. So we're going to talk about Interface Builder during this session.

This is our agenda. I want first to introduce Interface Builder, give you a brief description of what Interface Builder is about. I will use the word IB very often because this is what we use for short. And then I will go into details of how to create your user interface.

Basically the three steps it takes to use Interface Builder to develop your application. How to create your user interface, how to connect your user interface to your code, and then how to load your user interface inside your application to display your user interface. I will give you also some tips and tricks and we will show a demo of the CodeWire integration with Interface Builder.

So let's start with what is Interface Builder. So as John was saying, Interface Builder is Apple's tool to create, to prototype your user interface for both Cocoa and Carbon. It's Aqua compliant, so you're sure that if you use Interface Builder, your application will be Aqua compliant. As I say, it's for both Cocoa and Carbon. And recently, we've added Apple Script. So you can now develop an application using Apple Script as your language.

So here we have Interface Builder. It's an application. And Interface Builder creates what we call a Nib file. And we have two types of Nib files. We have a Cocoa Nib file and a Carbon Nib file. They are the same, but they are different. So you cannot use a Carbon Nib file inside a Cocoa application or use a Cocoa Nib file inside a Carbon application. They are different beasts.

But they are basically the same structure, and Interface Builder can load both of them. So from a Cocoa Nib file, what can you do? You can create a Cocoa application. You can also create a Java client for WebObject. And as I said, we've added recently Apple Scripts. We can develop an Apple Script application, which basically use Cocoa underneath.

And from a Carbon lib, you can create a Carbon application for Mac OS X, and you can create a Carbon application for Mac OS 9 using Carbon lib. We've been part of Carbon Lib since 1.1. So those Cocoa Nib files are basically a repository of objects. They are archived objects. It's especially true for Cocoa Nib. They are really Cocoa objects inside this Nib file. For Carbon Nib, with the new HI object, we're going to go more and more in this direction, having real objects within the Nib file.

So let's talk about how can you create your user interface using Interface Builder. So we have several tools to do that. And I'm going to go through several of them. Some of them are more recent, some of them are older tools, but all very useful to be able to create very quickly a user interface.

So let's talk first about the guides. This is something we've added a year ago, I think. They provide a way to be sure that your user interface conforms to the Aqua guidelines. It's a much intuitive way to lay out your user interface. It's very, very easy. I will show you a demonstration after. Very, very easy to lay out your user interface using the guides. And you have two types of guides. We have what we call the Aqua guides and what we call the user guides.

So the Aqua guides are very easy. You drag a button inside the window and automatically we show you what is the best location for this button. What is the best distance to the edge of the window, like in picture one, or the best distance between two buttons according to the Aqua guidelines, like in image number two.

I will show you that after. The user guide is something I'm sure you've used in any layout program like PageMaker or whatever. It's basically lines you can put on top of your window and you can easily align objects onto those guides. Those guides are saved with a Nib file so next time you reopen the Nib file those guides are there.

The layout track is something a little bit different. With Aqua, you have shadows. So sometimes it's hard to see where our control stops because of the shadow. So we've added those layout tracks. It's a very easy way to show you where is the bounding box of a control without a shadow.

And the size of those boxes is the size that's in the Aqua guidelines. Like a button is 20 pixels high. If you look at the button with a shadow, it's much bigger than 20 pixels. But the layout tracks show you exactly what is the real size of the control. And you can easily toggle them between hiding them and showing them.

The next one is distance measurement. That's a way to show you the distance between two objects. We have an inspector in Interface Builder that gives you the location of a control in a window, but it gives you the location to the parent, not a location between the control next to it. So with the distance measurement, you can measure distances between two objects. And it's triggered with the Option key. So let me show you those three tools before continuing.

So this is Interface Builder. So I'm going to create a Cocoa Nib file. So for people who have never seen Interface Builder, let me just go quickly through the different parts. This is the menu editor. If I close it, this is... It edits the main menu, the menu bar. This is the menu editor. Here I have a window. I close it. This is this object inside. My GIMP file has two objects, a menu and a window.

I have here the palette with different objects, so I can choose different controls. And if I bring the inspector, I can inspect an object, so this is a title, normal thing. So let me put some objects inside the window to show you first the Aqua guides. So I take a button. And as I bring it to the edge of the window, it automatically shows you what is the right position for this button. I can bring a second one. and he shows you also the right distance. Let me bring a table view, for example.

TabView, sorry. And same thing, I can build my user interface. We can do something interesting. For example, if you have a text field, and I want to align a label correctly. You can see here that I show you the baseline for the text so I can easily align the text with the baseline of this text field.

We do also something very nifty. For example, if you bring your radio button, the guidelines say that there is a distance, there is an indent from a text. So we show you exactly the right position according to the guidelines. So let's say now that I have a piece of text here, and I want to be able to have a piece of text in the same-- on the tab-- the other tab at the same location. For that, I can use the guides.

I can, for example, add a vertical guide, move it in position. I had an horizontal guide. Move it in position. And now I can go to my other tab and easily move the text at the right position. So this is a very useful usage of the guides. If I want to get rid of them, you just drag them out of the screen, of the window, and they're gone.

The layout text, as I said, you can show the layout text by just asking, show me, hide and show the layout rectangle. So you can see here, for example, you can see the baseline and you can see very now easily where is the bounds of this control. Without the layout rectangle, it would be hard to see that the text is much longer than it is.

So you can see exactly where things begin and end. And finally, the distance measurement. So I can select an object by pressing the Option key and moving my mouse on top of other objects or the container. It can show me the distance between objects. So let's go back to the slides.

The next feature we have to facilitate your creating your user interface is what we call logical grouping. In previous release of Interface Builder, if you wanted to keep objects together, you had to create a container, put those objects inside this container, which means at runtime you had an extra view that was not very useful. It was just there at design time to keep objects together. So we've added logical grouping, which allows you to group objects together, but they are just grouped together at design time. They are not grouped at runtime.

So I will show you that also later on. Once you group objects, you can see this little dotted line that shows you that the objects are grouped together. Very useful for text in a text field or something like that. By the way, everything I'm talking about here works both for Carbon and Cocoa. When there is something that will work on only one of the two, I will tell you. But everything I'm saying here works for both Cocoa and Carbon.

Locking. Also, sometimes you put objects on a window and you don't want to move them. They are fine where they are. You don't want, by accident, to move them. So now you can lock objects. You can lock their position and their size. It works for both controlled views and windows. And I show you for windows. It's a very, very useful feature for windows.

We have something we call Pop and Drag. You can find another name, it's kind of a nice name. It's an easy way to move objects between containers. It was very hard in previous release of Interface Builder to move objects out of a container and move it into another container after the fact. So we fixed that by having this new, it's more of a gesture, to pop objects out of a container and drag them into another container.

And for Cocoa developer, all connections are maintained. If you have used IB and you have a connection and you cut a button, the connection will be gone. Pop and Drag maintains all the connections so you can move objects between containers. You can even move menus. So you can take a sub-menu, move it to another place in the menu hierarchy, all by simply dragging.

The last thing I want to talk about is our new support for Spring and Strut. This is only for Cocoa. In previous years of Interface Builder, if you resize a window in ID, the controls don't move. They don't follow the Spring and Strut you've set for those controls, which sometimes is nice because you just want to have more space in a window.

But sometimes you want to keep the layout and just make the window bigger, keeping the layout you have. So by pressing the control key and resizing your window, now we apply the Spring and Strut. So all your settings are maintained and the window resized exactly like it will resize at runtime. So let me show you that.

So, logical grouping. Let me turn off the OutHack. So here I have a text field and a text field too. I want to be able to move them together, so I have to remember to select them together and move them. What I can do now is just simply say "group". and now I can move them together. They still resize independently.

But you can move them together and they will stay together. Very useful. We are also looking. So here I'm very happy with my design. I don't want to move.

[Transcript missing]

So they are locked. And you can easily, you can go to the size inspector if you want. This is very slow. And you can lock and unlock one specific object.

Something interesting here also is that, I don't know if you noticed, when you place a window in Interface Builder, for example, I move my window here, at runtime, this window will open at this exact position. So the position you have in Interface Builder is the position you're going to get at runtime. So if you put your window here and someone else comes and moves the window here and saves the Nib file, the next time the Nib is going to be loaded, the window is going to be there. And you don't want that.

So that is also looking on Windows. So I'm happy with this position here. I can go to the...

[Transcript missing]

The final thing is Spring and Struts. So let me set up my Spring and Struts for this. So I want this one to resize vertically or horizontally. I want this one to keep it here. So I set up my layout, but now I'm resizing Interface Builder. Oops, I forgot to.

I resize the window, but nothing moves. Because Interface Builder thinks here that, oh, you just want to make the window bigger because you want more room. But if I want to... If I really want to resize it and maintain the layout, I can press Control and resize the window. And it will respect all the spring and struts.

So the next thing, you've laid out your user interface, your API. Now you need to be able to connect this user interface with your code. And you want, when the user clicks on the button, something happens. You want, when the menu item is selected, you want something to happen. So this is what we're going to talk about.

As far as doing layout, Cocoa and Carbon are very, very similar. There is all the features we have for Cocoa, we have them for Carbon, most of them, if that makes sense. As far as connecting your UI to your code now, Cocoa and Carbon are very different frameworks. They have a different API, they have a different model. So the way you use Interface Builder is very different. Carbon has a procedural API C. Cocoa is an object-oriented framework and it has a very dynamic language objective C. And Interface Builder takes advantage of this feature.

So let's start with Carbon. If you have a Carbon programmer, Interface Builder does not change your model. If you know how to program Carbon, you know how to use Interface Builder. We don't provide a new model, a new way to do Carbon development. We just allow you to lay out your user interface and that's it.

We don't give you a new model to program Carbon. It's just a better way to, we think, to lay out your user interface and package your user interface inside your application. And also, it's very much easier using Interface Builder to take advantage of the new Carbon Event model.

So if you're a Carbon developer, you want to do two things. You want to be able to get a reference to a UI element. I want to get a pointer to this button. And also, you want to be able to react to a user action. The user pulled on a menu, select a menu item, and something must happen. This is usually what you want to do.

So how do you connect your UI to your code in Carbon? To be able to get a reference to a UI element, in Interface Builder, simply assign control ID to controls, menu IDs to menus, the same way you would do with any other tool. We allow you to set those control ID, menu IDs inside Interface Builder. In your code, simply code the correct API to get a pointer to this control. If you want to get control by ID, or if you want a new, I don't remember the name, HIView, get control, brand new API, so forth, they all work.

If you want to react to a user action, in Interface Builder, assign a command ID. We allow you to do that either to a menu item or to a control and implement the event handler. Same way you would do it if you were using any other tool or you would do it by yourself. So let me show you that.

So this time I'm going to create a Carbon menu, a Carbon Neb. So as you can see, basically the same thing. The palettes have changed. Carbon has different UI, so we have different palettes. But you can recognize all the control for Carbon. So let's say I have a text field and in my code I want to be able to get the content of this text field.

What you do in Interface Builder, you bring the Infopanel, go to Control and simply assign a signature and an ID. Save your nib and in your code, do a Get Control by ID and you're going to get a pointer to this control. Now I want to be able to react to some user action, so let's put three buttons in there.

[Transcript missing]

So what I can do here is assign command ID. And because I don't want to write any code on stage, I'm just going to use standard command ID that already exists in the system. So for minimize, I'm going to use the minimize window. For zoom, I'm going to assign zoom. And for quit, I'm going to assign quit.

You can also, if you want, type your own command if you have your own command to assign. And now what I can do is I can go to test mode. So Interface Builder has a test mode where you can test your user interface. So I go to test interface.

And what it does is just instantiate the Nib file like if you were in a Carbon application. So I have my window and I can say minimize. I can say zoom. I can say quit. Any quits. I didn't write any code. Just assign standard command ID that exists in the toolbox. Let's go back to the slide.

So now Cocoa. For Cocoa, also I want to point out that for Cocoa developer, you have to use Interface Builder. There is no choices. It means Cocoa is completely part of the development process for Cocoa development. You have to use Interface Builder. So there are four concepts for Cocoa development that you have to understand.

This is the concept of outlet, target action, file owner, and first responder. Outlet, target action are also covered by the word connections. When we talk about connections, we talk about outlet or target action. Those are the four concepts that you have to understand if you want to really take advantage of Cocoa and Interface Builder. Sometimes I see people saying, oh, I don't know what first responders is. I just ignore it. You won't be able to create a good Cocoa application if you do that.

So let's start. Outlet. Outlet is just a fancy word for an instance variable. It's just an instance variable inside an object, like any other instance variable. The difference between an outlet and any other instance variable is that this instance variable is graphically initialized by making a connection inside Interface Builder.

So you never go and set this variable. It's done within Interface Builder by drawing a line, by graphically connecting a source and a destination inside Interface Builder. But it's basically an instance variable, a pointer to some other object. So, for example, I have an instance of a class foo, and it has two outlets, a window and a button.

And inside Interface Builder, I can say this window instance variable is this window here. That I have on the screen. This button is this button here that I have on the screen. So it's just a faster way to initialize all the instance variables, all the pointers you need in your program.

Target action. So a target is just an object. But it's a special object. It's an object that will respond to some user action. The user click on the button, some object will do something. The user select a menu item, the target object will do something. And what it's going to do is what we call the action. It's a method on this object that will be in charge of doing something. And it's invoked by the user interaction. And like outlet, you graphically set up your target action inside Interface Builder by drawing lines, which we call connections.

So those are very important concepts and those are easy to understand. So here I have a button. A button has a notion of a target and an action. A target is an instance of an object. Here, a foo. And when the user clicks on the button, I want the do something method to be called on this foo object.

So the connections, when you make your connection inside Interface Builder, all those connections are saved within the Nib. And at runtime when you load the Nib file, all your outlets are going to be initialized for you, all your controls will be ready to code the right piece of code. You don't need to do anything in your code. Everything will be set up for you when the Nib is loaded.

Something new we've added in recent release of Interface Builder is what we call typed outlet. In previous release of Interface Builder, all outlets had a type of ID, which means whatever you want. There was no type checking as far as outlets. We've added a typed outlet recently, which means that now you cannot connect an outlet that requires an NS menu to an NS window. Interface Builder will not let you do that.

So we do a type checking to be sure that the outlets are correctly connected. If you don't want this behavior, for some reason, you can always use ID everywhere and you'll get back the old behavior. So let me show you a demo of outlet and action. Here we go.

So I'm going to create a Cocoa Neb again. So let's say that I want to create an application that displays an image inside an image view. And I want to be able to open and close a drawer using a contextual menu. I want the user to be able to right click or control click in the image, have a menu show up, and having an option to hide and show a drawer.

So let's do that. I did the wrong one. So I'm going to start with an empty nib. There is nothing in it. So first-- Let me drag this object here, which is basically a pre-made object that contains a window and a drawer. I drag it here, and what I get here is several objects.

I get here, this is the content, what will be the content of the drawer. I have my window. And I have this object here, which is the NS drawer, which is kind of a controller object. It maintains the relation between the drawer and the window. So I get those three objects when I drag this icon in my nib. So let me put an image view.

So what I want to do is be able to, as I said, I want the user to be able to control click and get contextual menu. So I need a menu. So let's get a menu. I have an object here which is a simple menu. So I drag my menu. It means an instantiate menu. And I'm going to rename it. I'd info.

Show info. So far I haven't showed you anything about outlet and action, but that's going to start now. How can I show a contextual menu? I have this image view here, and if I go to the If I go to the NSImageView class, I notice that there are three outlets.

There is a formatter, I don't really care. There is a menu, hmm, seems interesting, and nextKeyView. So what happens is that if you set this menu outlet here with a menu, you're going to get a contextual menu automatically. So let's do that. Let's control-click here and drag it.

Like a connection between the image view and the NS menu I just created. And say, menu, connect. So here I'm creating a connection. The source is the menu outlet and the destination is this NS menu I created here. So let's try that first. Go to Test Interface, control click, and I'm on user. It doesn't do anything because it doesn't know what to do. We haven't told him what to do for hide info or show info. So let's do that now.

So that was the outlet. By simply connecting the outlet of this object, which is an instance variable of any NS view, in fact, I was able to get a contextual menu by connecting this outlet. But now what I want to do is I want something to happen when I select the hide info or show info.

So I'm going to make another type of connection, which is a target action connection. And what I want to do is connect the hide info to the NS drawer, which is the controller object that knows how to open and close the drawer. So same thing here. If I select the drawer and go look.

[Transcript missing]

So I control click here and connect to the NS drawer. And I say I want to close. And I want to open. And now I can run test. Show info. Add info. I didn't write any code. I just connected-- By just connecting an outlet and two target actions, I was able to basically do a lot without any coding.

[Transcript missing]

I talked about Outlet, instance variables, target action, a way to have something happen when the user clicks on a button or a menu item. The next two concepts are the concept of File Zoner and First Responder. When I drag the object inside the Nib file, they are real objects. When you see a little icon for a window, there is a real window inside the Nib file. It's a real object.

You can instantiate objects, you can make connections, you can initialize instance variables, so you're dealing with real objects. FileZoner and FirstCastPonder are not real objects. They are proxy objects. They represent other objects. And those objects are not defined in a Nib file, but they are defined outside in a Nib file and they are defined at runtime.

So let's start with the file owner. So the file owner is an existing object. At runtime, they're going to be an object, an instance of a class that's going to be the file's owner. But it's external to the Nib file. This object is specified when you load the Nib file. Usually you use loadNimName owner, and you pass the owner. This is the file's owner.

And this object is special. It owns every object inside the Nib file. When you have a view in your view hierarchy, the super view owns the sub view. But at the top of the Nib file, there is nothing above, except there is the file's owner. So the file's owner owns every object that you see in a Nib document window. All the top level objects are owned by the file's owner.

And the file's owner allows you to make connection with an object outside of the Nib file. If you could only make connection within the Nib file, it would be like a little bubble, and you could not get out. So the file's owner gives you a way to reach inside the Nib file and make connection. And also the file's owner owns all the objects inside the Nib file.

The first responder is also a proxy object, but it's not a real object. It's more of a status you confer to an object at runtime. It's the first object in a responder chain to respond to a specific message. And depending on the focus, which text field has a focus, and what type of message, the first responder will change. So it's not one specific object. It's whatever object at the time is the first responder.

So let's take an example of a responder chain, a kind of a simplified view of a responder chain. I have an application. The application has one window, and inside this window there is one text field. Every object which is a responder in the app kit in the Cocoa framework has a notion of a next responder. So the user is happily typing inside this text field, and he goes to the menu and says, hide window.

So the hide window message comes to the text field, but he says, I don't know how to hide the window. So the message is passed to the next responder, which is the window. And the window says, yeah, I know how to deal with hide window, so it's going to hide the window. So-- The target here is the first responder. The action is hide window, but there is no real object. It's whatever object in the responder chain can respond to hide window.

If I have a copy message coming now, the user selects the copy menu item. Copy comes to the text field and says, "Yeah, I can easily handle the copy." The first responder is very useful for connecting action to an unspecified object. For example, cut, copy, paste. If you have ten text fields inside your window, you don't want to make ten connections to every text field.

You just want to say, "Do cut, copy, paste on whichever control has a focus right now." It's useful for hide window and things like that. It's also useful for connecting an object to an object in another Nib file. If it happens that this object is in a responder chain, through the first responder you can make a connection to this other object. Let me show you something.

So I'm going to create another Cocoa application. So if you look at the menu-- let's put a text field. Transcripts, Editing, and Post-production The connection is to the first responder copy. It means it's a connection. I didn't connect it to this text field here. I just want to connect it to the first responder saying, I just want to send a copy to whatever object will be able to handle the copy. Same thing with paste. The connection is to the first responder. So what I've done here is I just dragged to text field. If I go to test mode, I can type, can select, and I can copy.

and I can paste. I didn't do anything. Just because by connecting cut, copy, paste to the first responder, everything that's under cut, copy, paste now if you have the focus, if it's the first responder, will be able to cut, copy, paste. If I add a text view and I go back to test interface, same thing.

Cut. Paste. So, it just works. So this is very useful for connecting an object, connecting something to an unspecified object. Use the first responder. Very important concept. Go back to the slides. So you've created your user interface, you've connected your user interface either in Cocoa or Carbon, but now you want to be able to load your user interface inside your application.

So here again, there is a difference between Cocoa and Carbon. In Carbon, it's always explicit. You always say, please load this nib file. You give the name, the nib file is loaded. For Cocoa, there is one special nib file we call the main nib, and the nib file is going to be loaded, the first nib file is going to be loaded when the application is launched. All other nib files need to be loaded programmatically. You need to have some object saying, load this nib file.

So in Carbon, all the API to deal with the file are located in one header, the idcarbonruntime.h. There are six functions, very heavy API. And it's part of Carbon for-- Part of Carbon Framework for Mac OS X and is part of Mac OS 9, part of Carbon Lib for Mac OS 9. So you can use Lib file also in your Carbon Lib application.

So here is a very simple Carbon application that deals with a Nib file. First you have to create what we call a Nib reference. You pass the name of the Nib file and you get back a Nib reference. The name of the Nib file is like main Nib and it needs to be located somewhere into your application bundle.

Then you can extract objects out of this nib file. Objects have a name. Under the icon you see the name and menu, window. So you just give the name of the object. For example, here you can say set menu bar from nib, giving the nib reference you've just created, passing the name of the object, and we put up for you the menu bar on the screen.

You can create a window, pass the nib reference, pass the name of the window, we return you a window reference. Once you're done with the nib, dispose of the nib reference, and now you can show the window, run the application, use a normal Carbon API to deal with your application. You get a window ref, you get everything is a normal Carbon object.

For Cocoa, as I said, there is a notion of this special Nib file, which is a main Nib file. This main Nib file is automatically loaded when your application is launched. You can change the name. We call it main, but it can be any name you want. You go to Project Builder, and you can change the name of the main Nib file in Project Builder. Usually, this Nib file should at least contain your menu bar. This is the piece of UI you want to show up on the screen immediately.

So at least you should have the menu bar. You may have other windows in there, but you should have at least the menu bar. And the file owner of this Nib file will be the application. I was talking about the file owner before. The application will be the owner of every object inside this Nib file.

To load other Nib files, you have to use NSBundle. There is a method on NSBundle, loadNIP name owner. So all other Nib files need to be loaded when you need them. And if you use NSWindowController, you can use also NSWindowController to load your Nib files. It's also a nice way to load Nib file. And there is a sample in the developer example Interface Builder that shows you how to use NSWindowController to manipulate multiple windows, multiple NIPs. So if you look at multiple window, look at this example. It's a very good example to deal with multiple windows.

So now I'm going to go through a bunch of tips and tricks. Mainly questions that I've seen over and over in different mailing lists. So I'm going to go through that right now. So first one, break up your nibs. I see a lot of nibs that have like 20 windows, a ton of stuff in there.

This is not the way to deal with nibs. Nib file, you should not put your entire UI inside one nib file. And this is, a Carbon developer needs to be aware of that. In Carbon, traditionally with Resource Manager, you are putting all your resources in one big resource file. This is not the way a nib file works. You need to break up your UI among multiple nib files.

If a nib file is small, it will load faster. And also, it's much easier to reuse. If you have this big, giant nib file and you just want to reuse the about box, you have to go in there, rip out the window, put it into some other nib. If you have your nib file nicely break up, you can reuse your nib file much easily. So, typical bad nib, this is not the way to do it.

What you have to do is break up your nib. So here I have an application which has a main menu and a main window. So I want to put that in my main nib because I want that to be up on the screen immediately. But then I have an about box. The user may never look at the about box. So why put it in the main nib and be loaded immediately? I have a connection panel. Same thing. The user may never use the connection panel. And I have a preference.

The user may never use the preference. So you don't want to load a UI you're not going to use. So you need to break up your nib in multiple pieces according to your application usage and load those nib files when it's time. This is true for both Cocoa and Carbon.

Top-level objects. This is specific to Cocoa. I talk about the top-level object. That's the object you instantiate in your Nib. When you drag a window inside a Nib, when you drag a menu inside the Nib window, you basically instantiate an object. So it can be a window, a menu bar, and some other object. The file owner and first responder are not, as I said, not real objects.

You instantiate those objects. This means it's like doing NSWindowAllocInit. So somewhere in your code, if in your code you write NSWindowAllocInit, somewhere in your code you're going to have to do NSWindowRelease. You're going to have to release this window. Otherwise, you're going to have a memory leak. So the same thing applies for objects inside a Nib file. When they are instantiated, they have a ref count of one. So someone has to release them. Otherwise, every time you load a Nib file, you're going to have a memory leak.

You need to release those objects. So that's usually the task of the files owner, because the files owner knows about those objects and can release them when they are not needed. The NSWindowController gives you also a nice way to do that. It kind of hides this problem and does it for you. But if you don't use NSWindowController, you need to release your objects. We've added a lot of top-level objects recently. Now you can instantiate a formatter, a menu. So you have to be aware of those.

So that's the reference counting problem. There is one exception to this rule. NSWindow has a flag in the inspector. There is a flag that says "Release on close." That means that if the window is closed, the window releases itself. So for windows, for NSWindow, you don't have to worry too much about reference counting. The window will release itself on close if you check this attribute. If you check it and you release it, you're going to crash. So be careful.

Standalone views. That's something we've added a year ago or so. And this is a very nice way to deal with a view that don't have a window. In the old days, to be able to create a standalone view, you had to, inside Interface Builder, create a window, and at runtime, rip out the content of the window and get rid of the window. You don't have to do that now. You can just instantiate a view without a containing window inside Interface Builder. For that, just drag a custom view, and you're going to get a view standing alone.

So you don't need to do this trick of creating a window, taking out the content view, etc. It's very useful for the drawer. I was showing you before, the drawer requires a view, so you can use that. For toolbar custom items, for tons of stuff, it's very useful to be able to instantiate a view without a containing window. Same thing here. If you instantiate a view as a top-level object, be careful of the reference counting, because someone will have to release this view.

Initialization, also for Cocoa. I think that's the most popular question. To be able to do-- you load a Nib file, but you want to do something when the Nib file is loaded. So what you should not do is try to override init, init with frame, init with coder. They might be called, they might not be called.

Don't try to rely on one of those init methods. The right way to do post-NIB loading initialization is to implement AwakeFromNib. AwakeFromNib will be called on every object in a Nib, even the file's owner, not the first responder because it's not a real object, but the file's owner will be called.

All objects inside of a Nib file, if they implement AwakeFromNib, this method will be called when the Nib is finished loading. All the connections are set up, all the target actions are set up, all the objects have been instantiated. So, do not try to override init, init with frame, init with code, that will not work. Implement AwakeFromNib.

New Nib format. So in Jaguar, AppKit has introduced a new archiving model. And Interface Builder used the Cocoa archiving model, and so we take advantage of this new Nib format. It's a very interesting format because it's a key value type of archiving. And it provides forward and backward compatibility.

So all Nib files will work on future release. Future Nib files will work on older release. So that's a big, big advantage which we don't have with the current archiving model. This is only available on Jaguar and on future release of Jaguar. That will not be available on 10.1.

So we've added a preference in Interface Builder that allows you to take advantage of this or not, of this new archiving, and we have three settings. We have 10.1.x only, which means that it's the old archiving model, and it will work on every version of Mac OS X, even future version. But you cannot take advantage of new features of Cocoa. If Cocoa creates a new widget or add new properties to an object, the old format will not be able to read and write this new property or new object.

We've added also Jaguar and Letter-Only, which is the new archiving model, only, which means it won't work on 10.1, but it will work on any future release of Mac OS X. And we've added a Both, which gives you the best of both worlds. Basically, we save both versions, both archiving in a nib. So you have both versions in a nib file. So you need to choose which one you want to use.

Carbon, images, that's also a question that comes up very often. For Cocoa, it's much simpler. But for Carbon, people had problems before dealing with images. In IB, we have a tab that says images, so you can see your image, like your icon, inside Interface Builder. The way to do that is that you need to put your images inside your project.

They have to be part of your project, your Project Builder project. And they have to have the same target as your Nib file. If you have a target deployment for your Nib and you have a target test for your images, you won't see your test images into your deployment target. The images and your Nib have to be in the same target. I think the mistake people make most often is that the image and the Nib are not in the same target.

They have to be in the same target. They also have to be compiled resources format with a .rsrc prefix ending. And we support ICON, ICNS, CICN, and PICTURE. So if you have any of those images inside the .rsrc file and the target and the Nib are the same, you'll be able to see your images in Interface Builder and be able to see drag them into button and stuff like that.

The last point is NibTool. NibTool is a little command line tool that works for both Cocoa and Carbon nibs. There are lots of options for Nib tools, so I would suggest you to look at the main page. For Nib tool, there are really a lot of options. It's used by File Merge to be able to diff Nib files. And the main usage we have of Nib tool at Apple right now is to localize Nib file. So let me show you.

Let's say you have a-- you develop in English and you want to be able to--

[Transcript missing]

So the way to do that is to take your English nib. Don't worry when you develop. Don't worry about the other languages. Develop in English or any other language. And using the nib tool, you can extract all the string from this nib. And you can create a text file with hello equal hello, close equal close, open equal open. So you have all the strings inside this nib file. Send this text file to a localizer. It's going to return French in this case.

And by reusing the nib tool, you can use the original English nib and the new localized text file and regenerate a French nib. So we do that automatically at Apple. We automatically localize all the system like that by just using the nib tool and going through this process. It's much easier to localize your new file. It works great. So I would like to invite now Isaac from MetroWorks, who's going to show you the new CodeWire and IB integration. Thank you.

[Transcript missing]

Okay, well it's clearly evident that Apple has a great revolutionary tool with this Interface Builder. And previously our Code Warrior developers have wanted to use the nibs and add them to their Code Warrior projects, but in the past it's been kind of a pain and really difficult to use. So we've worked closely with Apple and their Interface Builder team and we've come up with a solution to integrate the two tools in the same manner that Interface Builder and Project Builder have worked together before.

So now with Pro8, you can add your Nib files to the projects in Code Warrior and you can build your applications using Code Warrior. With our Objective-C C++ compilers and the new addition of the long file name support in our IDE, you have the Cocoa framework available to you now.

So whether you're doing Cocoa applications or Carbon Nib-based applications, you can create these applications in your favorite IDE, whichever one it may be. So let me go ahead and do a short demo for you and show you how to add Nib files to your Cocoa and Carbon Nib projects. And then I'll turn it back over.

So I already have a simple Cocoa application set up. And it's kind of similar to the silly balls from the old days. Let's see here. So we have a nib file in here and we already have a circle image in here so that will show up in our nib file when I launch it from Code Warrior.

So we have this circle image which we can use throughout our UI and we already have a button down here which uses it. And let me run it for you real quick so you can see what it does. It just draws a circle in a random place within this view. We can stop it and start it. And this is just a button that tells which image to draw in the view.

So let me go back to the source file here. And I have a little macro set up. And if I switch it over to one, you know, I have some other code so that I can add a few more images and handling and such. And from Interface Builder, I'll create a couple of new buttons. And what I want to do, let's go ahead and hide I have a couple more images on the disk that I want to add to my Code Warrior project. So I'll just drag them in.

and if we go back to the nib file, we'll see that they've automatically been added to our images pane so that you can use them in the UI. So I'll drag the MetroWorks image over here, and then I've got another Motorola logo. And let's go ahead and connect these buttons to the view so we can draw different images.

First of all, I'll need to come over to my classes and re-read the header file since I've added a couple new outlets. Now when I drag this up here, I have this new set draw MetroWorks, which was in the header file. And I'll just connect that one. And I'll do the same for the Motorola image and say, "Set draw Motorola." And I'll connect those up. Then come back to Code Warrior and run it.

And we have the new buttons that are being used. And clicking on them will change the image. And so the new bundling mechanism that we're using in Code Warrior, as soon as you add them to the project, it will realize where it needs to go into the resources folder of your bundle application along with the nib files. The other thing I wanted to show you is we can, you know, if you want to do a new class from here, just create a new subclass.

And then from Interface Builder, you can create the new files. And it'll bring up a save dialog and ask you which-- It'll recognize that you have a project open in Code Warrior and ask you where to save these files to. So... "And we'll just go ahead and add it to the Cocoa Balls target." And if you do create a new nib file, just make an empty one, and as soon as you save it to the disk, Interface Builder will recognize that you have a project open in Code Warrior and it'll ask you to add this file automatically to it. So we'll go ahead and add it to there. Come back to our project.

And we'll see that the new untitled nib that we just made was added along with the two files that Interface Builder created. That's what I have for the Cocoa example. So let me bring up a Carbon one and we'll This one already has the Nib file and, like Henri said, you need a compiled resource file, which already has a couple of images in it. But I'll open this up. And this is just a simple example from the developer CD.

And if we come over here, we just have a little picture down here and a color icon that I've made. And so let's go ahead and... Duplicate that. We can drag our image into there. And over here I have just an empty pic that I've already put in there. We can drag that.

And when you run this, Again, you have your icons that were used. And, you know, creating the new nib file from Interface Builder will add the nib to your Carbon-based application project as well. And that's all I have, and I'll turn it back over to John. Thanks a lot.

Alright, well here's the documentation slide that you're used to at the end of every session. This is where you can get more information about Interface Builder and the tutorials and then the website itself. The roadmap for other sessions related to this or some of the topics that were touched in here are 905 for Apple Performance Tools and the rest are listed there. Cocoa Drawing, etc.

Most importantly is the feedback forum for development tools. Because Interface Builder falls into our development tools category, we'd love to hear feedback on this and any of our other development tools. Finally, if you have any questions about something that was talked about here or you're looking for additions to features that you'd like added to Interface Builder or additions to the documentation or to the tutorials or anything related to interface design, this is your contact point at Apple. That's me. Feel free to send me an email.