Developer Tools • 52:19
Interface Builder 3.0 provides a brand-new plugin architecture for developers to integrate their custom controls directly into the new Library window. Learn how to build your custom control as a plugin, how to give your control a unique look, and even how to create its own specialized inspector.
Speakers: Matt Gamble, Chris Pavicich
Unlisted on Apple Developer site
Transcript
This transcript has potential transcription errors. We are working on an improved version.
Good morning everyone. I'm Chris Pavicich. Joining me on stage today will be Matt Gamble. We're both interface builder engineers and we're gonna talk to you about creating custom plug ins for Interface Builder 3 today. I apologize if I'm a little hoarse. I've got a bit of a sore throat, so bear with me please.
So how many of you, show of hands, were at the introduction to Interface Builder this week or you've used Interface Builder before? All right, almost everyone. Super. So really quick agenda of what we're gonna go over today. We're gonna talk about Interface Builder. Interface Builder Kit, the framework responsible for doing all the heavy lifting for Interface Builder. We're gonna talk about the architecture of Interface Builder plug ins. And we're gonna, Matt and I are gonna walk you through building an Interface Builder Plug Ins step by step.
So who is this talk primarily focused at? It's primarily directed towards those of you developing custom views or controls for OS X. That wanna package them up and integrate them into Interface Builder 3. The talk's a little bit out of scope for folks who maybe have written one custom view or one custom control.
And you're using it internally on only project via, the whole point of writing IB plug ins is to promote reuse. So there you go. This might not be for you if you've just written one custom view. But if you're doing a bunch of custom view work, we think it's something you're gonna wanna look into further.
So, let's get started. What's Interface Builder? Interface Builders are graphical design and development tool. It's filled with all of the shipping on the system controls, preconfigured in the Interface Builder library. Uses real objects from start to finish, so what we're gonna see when we do our integration today is a view Matt and I will be integrating is, is a real view and it, we're not faking things up with graphics and images.
It's just really the real view we'll be integrating. It's primarily focused towards designers and engineers. And it separates, it promotes a strong separation of the bottle view controller. So great, that's IB. So Interface Builder kit. It's a new framework shipping in developer library frameworks. And it's the public API for Interface Builder.
There are three classes it exposed for you guys to subclass. Those are IBDocument, IBInspector and IBPlugin. We're really not gonna talk about IBDocument today, but we are gonna focus quite a bit on the IBInspector and IBPlugin classes. The other thing you'll find in the Interface Builder Kit framework, in the public headers, are two files filled with category methods declared on object and view. And these are the API you're gonna be implementing as categories on your view or object.
There's also a file full of geometry utilities, so if you need to do any sort of view geometry math, there's utility functions in there for you guys to use. And the important thing to remember is that this framework is installed in developer library frameworks, not system library frameworks. So, that's the Interface Builder Kit.
Let's talk about Interface Builder Plug ins. Plug ins in IB3 replace Interface Builder 2x palettes. They're simple bundles. If you've worked with Cocoa for a while you'll probably be familiar with bundles. There are three ways to get you plug in loaded into IB. Via Xcode. If you build and run the default Interface Builder template project, it'll automatically launch, build your plug in and load it into IB3.
There's a preference pane that you can set up plug ins to be loaded every time Interface Builder launches or you can double click any IB plug in in the finder and it will automatically launch and load Interface Builder for you. So why would you wanna write an IB plug in?
The first thing that you're gonna get from integrating your view or control directly into Interface Builder is what you see is what you get editing. You're gonna get a lot of reuse out of this as well. You're gonna have to write less code. And you're gonna be able to piggyback on the localization support we've worked pretty hard on in Interface Builder 3. So let's talk about those three points in a little bit further depth.
While Matt and I were working on this presentation over the past couple of weeks, we wanted to come up with a view to show you guys on stage that we were gonna integrate. And so we came up with this simple shape view. It draws closed polygons and it's pretty nice.
So we wrote a bunch of demo applications and while we were working with the new view we'd written, but before we'd integrated it in Interface Builder, Matt sent me a nib he'd been working on. And when I first loaded it up, I got this, which is a sea of blue custom views.
These are all actually the shape view that we'll be integrating, but it's a little bit confusing as to what's what in this nib. The other thing you'll notice is that there's, I've got the inspector open there and there's no inspector for the view. So there's no configuration I can do to the view that Matt me in IB, yet.
So great Matt, you sent me a sea of blue squares. Thanks a lot, this will be really useful whew. Not the best day being a developer at Apple ever. So Matt realized the error of his ways and he sent me the plug in for the shape view. And low and behold, I did load the plug in, I did reload the view and it turns out Matt being the total sweetheart he is, had drawn me this beautiful picture of a sunny day and my house.
I'm not sure why I have a fire burning on such a sunny day without snow, but, we'll go with it, thanks Matt. It's gorgeous. You'll see that the other thing that I got when I loaded Matt's plug in was an inspector that'll let me configure any one of these shape views that make up this gorgeous picture. So great. As I said, we worked with this view for quite a while before we actually wrote our plug in. And we ended up writing a lot of code that looks like this.
It's an awake from nib method and we're initializing one of our shape views and setting it up and setting fill colors and position. And great, it's pretty simple code. But it was scattered all throughout our project and working with things in code while it's fine is not nearly as nice as dragging things around in IB and resizing them and playing with inspectors.
So after we got our integration done, my awake from nib method went to this. Zero lines of code, why? Because I'm doing all of my configuration in Interface Builder. So comparing the two, this one to that one, show of hands, who thinks this second one is, has fewer bugs?
Yeah, we thought so too. All right so the third reason to integrate you control into Interface Builder 3 via plug in is that you can piggy back on our localization support. Of course if you guys are shipping apps, and hopefully you all are, and you've got your great views and controls you've written, you don't want that just to be targeted towards one market, towards English speakers or Finnish speakers or whoever it might be.
You want it to reach as broad an audience as possible. And we've spent a lot of time working on localization in the newest version of Interface Builder. So really streamlined and automated process. There's a bunch of new APIs available. Unfortunately, it's a little bit beyond the scope of this talk today to talk about it.
So I'm gonna suggest for those of you who are interested in localization and hopefully it should be all of you, that you consult the developer documentation. We've got a great tech writer. He's done a great job on putting the docs together for this, so they're out there, please use them.
So as I mentioned before, IB plug ins are just simple bundles. They're bundles that act as bridges between interface builder and your code. How do we bridge the gap? We bridge the gap by linking against Interface Builder Kit and by linking against in our case for Matt and I today, our shape view framework. Our shape view framework happens to have all the code for our custom shape view.
And there are a bunch of files in the Interface Builder plug in template project that you're gonna have to deal with. Writing a plug in doesn't involve writing a lot of code. In fact it requires writing very little code. But let's take a walk through and see what files you'll have to touch in that template project to get your plug in up and running.
The first thing you're gonna need to do is subclass IB plug in. The IB plug in subclass you're gonna write is gonna be responsible for doing any set up and tear down necessary for your plug in to work correctly when it's loaded by Interface Builder. For the most part, you won't actually have to do any set up and tear down. But if you need to, there's hooks there for to be called when your plug in loads and unloads.
It provides a list of library nibs to Interface Builder to be loaded so that your content, your custom view or control ends up in the library. There's also one method you pretty much have to override or should override, strongly suggested that you override that sets the label in the library.
The next thing you're gonna find in the template project is a library nib. We actually use Interface Builder to build Interface Builder so one of the things you're gonna have to configure is a nib with the content you want integrated into Interface Builder 3 and it's a pretty simple process and we're gonna run through it in the first demo. So this nib just contains the views and controls that you're gonna wanna put into the library.
Then these next three files I'm gonna talk about are each per view or control that you're gonna be integrating So every view or control needs an inspector. And this is the view loaded into the attribute inspector stack that allows you to configure your view. And what shows up in the inspector stack is based on document selection. So when your view or control is selected in the design surface, it's gonna ask your view, hey, do you have an attribute inspector that you'd like to contribute to the stack so that you can be configured?
The next file you'll find is an integration file. This is the bridge between your class and Interface Builder. And I mentioned a bunch of category methods earlier. Those category methods are gonna be the API you're going to implement to get your view correctly talking with Interface Builder. And that API is defined in the Interface Builder Kit. And the last thing is a class description file Class description file is a pretty simple plist, listing the class name for your view, its super class, so who is it inheriting from and a list of its actions and outlets.
So how do we build a plug in? It's a pretty simple process. And we're gonna start walking you through it. we're gonna go in three steps today. The first demo we're gonna do is building the library nib and the very rudimental plug in just to get things off the ground.
We're gonna talk about building an inspector for your view. And we're gonna talk about polishing off your plug in and adding the finishing touches and getting your plug in content to look as good as or better than ours does. So let's start off with getting your view integrated into the library.
What you see on screen here on the left is the library nib for this shape view that Matt and I will be integrating today. And I wanna talk about the parts of this for just a second. We've got the white square, it might be a little hard to see, no you can see it okay. Is a library template object. For every view you're gonna be integrating, you're gonna use one of these library template objects.
And inside of it or I'm sorry. The library template object is what the library knows how to load. Inside of that library template object is another view generally the view you're integrating. The custom class of this view here is set to our shape view. So it's drawing a nice pentagon is five sides, yes? My team is nodding yes, that is in fact a pentagon.
So you can see that we've got a pentagon loaded in our library nib. And that's what shows up in the library. As I mentioned earlier, Interface Builder works with real objects. So the real objects you're configuring in the library nib are the same real objects that show in the library and they're the same real objects that you'll drag to your design surface.
So this is the library template nib you get by default when you open up the template project from XCode. And we think we've done a nice thing here. And there's an example view at the bottom that's actually how button is integrated into the library. And there are tool tips set on all of these views.
So if you start working on your plug in and you get lost or confused when you're configuring your library nib, hover your mouse over any of these views. Wait for the tool tip to pop up and you'll get a really, really long and verbose description of what that view represents and what you should be doing with it.
So in our demo today we're actually not gonna use any of that example code. We're just gonna work with the one library template object that we have left. And we're gonna select the view in the center that will appear in the library. We're gonna bring up the identity inspector. And we're gonna set its custom class to shape view.
And at that point, we're gonna be done. One thing I wanna emphasize about building plug ins for the new Interface Builder is that it's very much a, an opt in model. You can do as little or as much of what John and I are, or what Matt and I are gonna show you on stage today. Sorry Matt. Hello John.
So at each of those points where we think you could quit, we're gonna try to remember to give a shout out today and say like, hey, you could stop here. For instance, after my first demo, if you only had one view you wanted to integrate, and you really didn't care about building an inspector, you could stop after what I'm about to show you and you'd be good to go. Of course, we think you should go through the entire process and leverage as much of the API as we've given you. But you don't have to.
( Period of silence )
So I wanna start off showing you today where you're going to find the sample project for Interface Builder Plug Ins. So I'm gonna fire up Xcode, the new project assistant is up, and you see there's an Interface Builder Plug in Project Template available for your use. In the interest of not walking you through a lot of boring set up today, we've actually got a template project already configured, so I'm gonna go ahead and work with that one.
( Period of silence )
So I mentioned earlier, plug ins are bundles. The one thing that every bundle on the system has to have is a unique identifier. So the first thing I'm gonna configure, so I'm gonna just close the targets. Select my plug in target, bring up the inspector.
( Period of silence )
And I'm gonna give it a unique identifier. There's a default one provided, but things will get mighty confusing for your users if you use the default one and they're also loading plug in code that that developer decided to use the default plug in identifier as well, so set your own.
And the next thing I'm going to do is open up the library template nib, double clicking that in Xcode should automatically launch it in Interface Builder. And as I said earlier, I'm gonna whack all this example code. Let me show you the tool tips first. There you go. So this is all explained.
( Period of silence )
Selecting things is hard when you're on stage. So as I mentioned earlier, there's my library template object, there's the custom view in the center. I'm gonna bring up the identity inspector and I'm gonna set the class of this to MC Shape view. The view that Matt and I are gonna be integrating today. And low and behold, I'm gonna save this. And we're done.
That was pretty simple. The other file I mentioned that you had to have per view that you're integrating is a class description and I have a class description already configured here for our shape view. Our shape view inherits from NS View. And it's about the simplest view you could integrate into Interface Builder because it doesn't have any actions and it doesn't have any outlets.
So I'm gonna go ahead and build and run this project. We've done a, a nice thing which is set up build and run in the template project to go ahead and launch Interface Builder and preload your plug in. So there's our shapes plug in, here's my shape view. I'm gonna go ahead and drag it out onto this window. And I'll duplicate it a bunch of times. I'm a really big fan of triangles.
So super, that took me 45 seconds? And my view is integrated. One problem with this though is, thank you.
( Applause )
All right.
( applause )
So this is all well and good. I've now got a bunch of triangles I can pull off the library and swell.
I can save this document, as long as I ship the plug in to any of my friends who wanna work with the shape view, things are gonna work out great. But there's one nagging issue here is I don't want these all to be triangles and I don't want them all to be white. Well, how do we configure things in Interface Builder? We do it with the attribute inspector and I don't have one. Huh. That's gonna be pretty hard to configure these things. we're gonna have to write a lot of code.
That's less than positive. Huh. All right, well luckily that's the next section of our talk is talking about how you write Interface Builder inspectors. So I'm gonna go ahead and save this file that I've created so Matt can use it later. And if we can go back to the slides, please.
I'm gonna recap what I just told you guys. So first thing you have to remember is to link the right frameworks. Our sample code linked against our shape view framework and the Interface Builder Kit. We had the set up the bundle identifier to make sure it was unique, done.
Set the label and the demo gods are not with today. That was in the script and I forgot to show it to you. Bad, bad, bad. And the last thing that we walked through was configuring the library template where I set the custom class of the view appearing in the library. So I'm gonna hand things off to Matt now and he's gonna talk about building inspectors.
( Applause )
Good job, man.
- Good luck.
( Applause )
So thank you Chris. So we were able to get our custom view into the Interface Builder library. But as Chris showed you, we weren't actually able to change any of the attributes that are specific to our view. So for that we're gonna need an inspector.
So here you see our inspector that we're gonna be integrating for our shape view today. Now for those of you who have worked with Interface Builder this week and it seemed like it was a lot of you, you've seen that Interface Builder inspectors are divided into slices where each slice is corresponding to a class in the inspected object's hierarchy.
Well that makes our job easier because all we need to do is add the attributes that are specific to our custom view. Now an inspector in Interface Builder is composed of two main parts. The first part is actual inspector view. Now this is the view with the controls that'll be synchronized to the custom view and this is the view that shows up in the IB inspector stack.
The second part is a custom subclass of the IB inspector class. And this is the class that will act as the controller for our inspector view. Now we won't actually be making too many changes to the code of this class today. But depending how you were integrating your view, you might need to touch this is a little bit more depth.
And also as Chris mentioned, it's important to point out that you're going to need one inspector subclass and one inspector view for each controller view that you'll be integrating.
( period of silence )
So now let's talk about actually constructing the inspector view. What you see on screen is the default inspector view that you'll be getting in the inspector nib that comes as a part of your project in Xcode.
You can see it has some sample controls. And these have been laid out in a manner that's consistent with the rest of the inspectors in Interface Builder. You also could probably notice those red lines. These are user guides that we've provided to make sure that as you are readjusting and moving around your controls, that you are making sure to keep your look consistent.
So at this point, the process of building your inspector view is just dragging in the different controls that you'll be using to reflect the attributes of your custom view. And it's important to make sure to select the, the right controls. Things like check boxes work well for Boolean values and combo box might be just the thing for an enumeration.
So now that we've constructed our view, and we have our controls that we're gonna be using, the next step is to actually associate our nib with the class that we'll be using as its controller. And for us that's our IB inspector subclass. So what we wanna do is select files owner.
And then bring up the identity inspector. And select our IB inspector subclass from the combo box. If you were using the template from Xcode and you have that project open, then through the magic of Xcode and IB synchronization, you should be able to just select it from the pull down menu. If not, simply type it in.
( Period of silence )
Now there are two methods for configuring your inspector. We have our inspector view built. We have it associated with our controller class. But now we need to make sure to synchronize our controls with the attributes of our view that they'll be reflecting. Now the two methods of this are Cocoa bindings, which is by far the easier of the two methods. You're leaving all the work to Interface Builder.
The second, if you're used to using actions and outlets and you'd prefer to go that route, that's fine. You'll just need to make sure to override the refresh method in our IB inspector subclass. You need to connect your outlets and actions to your various controls. And then make sure to modify your selection in your action methods. Now we definitely recommend using Cocoa bindings. It's much easier and it's much less error prone. Now since I'll take you through this process, since that's what we'll be using in our demo today.
( period of silence )
Now when we know that most of you when you're thinking about synchronizing controls in this manner, the first thing you're gonna wanna do is drag out an array controller and use that. now since we know that you're gonna do this, we've provided it for you.
There's a property of the IB inspector class called the inspected objects controller. And this is simply an array controller that reflects the current selection. And so when it comes to binding using Cocoa bindings, it's as simple as entering the key path inspectedObjectsController.selection.the name of your KBO compliant property.
So to do this, we would select the control that we're binding and bring up the bindings inspector. Now since we associated files owner with the class we will be using as our controller, which is the subclass of the IB inspector class, that we're gonna bind to files owner. And next in the model key path, we're gonna enter inspectedObjectController.selection.the name of our KBO compliant property.
( Period of silence )
So we have our inspector view built. We have our nib associated with our controller and we even have our control synchronizing through Cocoa bindings. So the last step is to make sure that our view appears as part of the inspector stack in Interface Builder. Now the way this works is Interface Builder simply queries the different classes that are in your, in the inspected controls hierarchy asking it if it has any inspector classes that it should be loading.
So what we'd like is to get our on the top of that stack. So we're gonna do this through a category method on our custom view.
( period of silence )
So in this category, on your custom view, called IB populate attribute inspector classes. We're gonna first make sure to call super.
And so this is gonna make sure that we have all the other inspectors that are a part of our hierarchy. And then next we're simply gonna add our custom inspector class to this array of classes. So now that we have seen how to do this, let me actually take you through the process and we'll return to the demo machine.
( Period of silence )
So I'm just gonna close down Interface Builder for now. And return to our Xcode project. So in the resources of our plug in, we see we have our MC shape view inspector. So I'm gonna double click on that nib and open it in Interface Builder.
And here you see the one that we saw on screen has a bunch of sample controls that have all been laid out appropriately. And the user guides to help us out. Now in the interest of time, I'm just gonna go through binding one control for use in our inspector. And that's gonna be a color well. So I'm gonna just get rid of these guys here. Simply press delete. And these as well.
I'm gonna put this in a more appropriate place. Here you can see we're using the user guides to make sure we're lining it up appropriately. And just drag this label up here. And now the property that I'm gonna be associating with this color well is gonna be the fill color of our custom view. So just make that a little more obvious.
So now and the last step, we have got a lot of extra room here. So I'm gonna drag this to make this a little bit smaller. And the easiest way to do this is to hold down the shift key and then when you're resizing, you'll only be resizing vertically and not messing with horizontally.
Now additionally, I could use the user guides to just do this on sight, but if I want to be a, a, make sure I'm exactly perfect, I can hold down the option key as well and there we can see it showing me the height and get it exactly to match the top.
Perfect. So we have our control laid out. So the next step as we discussed earlier is to select files owner. And then bring up our identity inspector. Now since we have our project in Xcode open, if I look down here I can see that our MC shape view inspector is in, appears in the list. So I can simply select that.
So now, returning to our view, select the color well we have here. And open the binding's inspector. Now we wanna make sure to that this fill color is gonna be reflecting the fill color property of our custom view. So turn down value. And we just associated files owner with our IB inspector sub class. So we'll be binding to that.
I'm gonna grab our fill color key path, return to Interface Builder. And in the model key path, I'm gonna enter inspectedObjectsController.selection and then the name of our KBO compliant property, in this case is simply fill color. So I'm gonna hit return. And there, we say it's all bound up. So we're done actually constructing and associating and binding our inspector nib. So I'm gonna make sure to save this and quit interface builder. And return to our Xcode project.
Now just to keep ourselves organized, we've created a separate file called our MC shape unit integration where we're holding all our various category methods. And selecting this we see that we have this method, IB populate attribute inspector classes. Now at this point, as we saw in Chris' demo, all we did not see the inspector that was associated with our custom view, we simply saw the one for NS view. That's because we are as good citizens calling super first. But now we need to make sure to associate or to insert our custom inspector as well.
( Period of silence )
And that's pretty simple. Just add our MC shape view inspector class to the array of classes. So if I save this, then I'm gonna build and go once again to open it in Interface Builder. And now, I can open that file that Chris created during his demo and here we have a bunch of our shape views.
But now, if I select one of these shape views and click on the attributes tab, we can see we have our fill color here and its correctly synchronized and it's showing that yes we indeed have a white triangle. Selecting this, we can make this something I don't know how about green. Great. Very quick, very easy.
( Applause )
So I'll make this guy a little bit larger, so we can see him. And maybe we'll wanna change this color instead to something like purple, that's nice. Well, maybe we want it to return to green. Well, this should be as easy just hitting undo. So go to edit, and undo.
Hmm. Okay. Well the size change that we made correctly undid, but we definitely changed the color from green to purple. And so that wasn't working. Well it turns out that the change in shape as we know is an attribute of our super class which is NS view where as this change in fill color is specific to our custom view.
So we obviously need to make sure to tell IB about the attributes that we have that are specific to our custom view because at this point, it does not know about them and cannot undo and redo appropriately. So I'm gonna turn it, if we could head back to slides. Oh, actually one last thing before we turn back to slides.
( Period of silence )
Thank you.
Now that inspector that we created, that was obviously just had the one property. It was a very simple inspector. Now instead of going through the tedium of dragging in a bunch of different controls and binding them all, we have a prefigured inspector. So I'm just gonna grab that one. I'm gonna delete this inspector we have in the project. Then I'm just gonna grab this preconfigured nib that we have. If that does not want to work. Bring this over.
And copy it in and that's the correct target. So I'm just gonna build and run once more so you can see what this inspector looks like. And again, I'm gonna open the file that we were working with. And so here we see a more fully flushed out inspector that's synchronized with all our different attributes. But we still don't have undo and redo support and there's a probably a few things that we could do at this point to clean things up. so if we could now turn back to slides. Sorry.
( period of silence )
So let me just do a quick recap of what we took care of in this demo. We constructed our inspector view, dragging in the various controls we're gonna be using to reflect the views of our, to reflect the attributes of our custom view. We set the class of file's owner so that we could associate our controller with our inspector nib.
We then used Cocoa bindings to bind these controls for our properties, taking advantage of the inspected objects controller. And then finally we just added one simple line of code into our integration category, our category method on our custom view, making sure that Interface Builder had our IB inspector subclass properly associated with our custom view. So now I'm gonna turn it back over to Chris, whose gonna tell you how to add those last few finishing touches.
( applause )
So I'm gonna talk about polish. At the end of Matt's Demo, undo and redo support didn't work. So at the point Matt stopped, really not a stopping point. But after you add undo and redo support, we will be at yet another one of those stopping points where you could quit here and you'll be done. So how does Interface Builder manage its undo stack? It's got an unlimited undo stack and almost every, every property of every view or control that you change should be undoable and redo able.
This is a really important point. And it's, it's how in fact internally we test to make sure things are working correctly. If it doesn't undo and redo, it's broken. You've done something wrong and you need to look at your code. Fortunately undo and redo support is very simple and you very nearly get it for free. It's a matter of in your integration class, writing, overriding one method. IB populate key paths.
Like building the inspector stack, Interface Builder will query your class for all of its attributes, and when it queries your class, the first thing your class should turn around and do is query its super class. So that when our shape view gets asked for its properties, it not only returns its own, but those for NS view. So as you can see from the code sample on the slides the first thing we do in IB populate key paths is call super.
And we follow that up by adding our own KBO compliant key paths to the end of that dictionary. With that done, Interface Builder knows what properties of our view to observe, can watch them, see when they change, dirty the document as appropriate, and it can manage the undo and redo stack.
So very important that you add all of the properties you need undo and redo support for and very important that you remember to call super so that you have not only your properties but all the properties of the classes above you in the hierarchy.
( Period of silence )
One of the things you may have noticed in our demos today that as we were dragging off our shape view from the library, it was staying at the small library size of 80 by 80. so when we pulled it into our design surface, it was tiny and it wasn't configured particularly well.
Well, there's a solution to that. In your library nib, your library template object has two outlets you can use to provide a better user experience to folks dragging your control off the library. The first of these is the dragged view outlet. And the dragged view outlet simply points to a preconfigured instance of your view or control.
If you happened to be integrating something that's not a view or a control, say a subclass of formatter or some other object, you can also use the represented object outlet and you set the represented object outlet to an instance of the object you want dropped into the design surface when you pull your control off of the library.
So the other thing you may have noticed if you've worked with IB this week in the seed, is that in the library we provide a lot of documentation for the controls we've integrated. We provide a very brief summary of what the controls is to be used for and we provide a more fuller descriptive text that hopefully helps users understand what the viewer control is to be used for. So in the demo today, I'm gonna go ahead and open up the library nib, configure those things and you'll see how they show up in the library.
( Period of silence )
So how do we do that? With the library nib open and our object selected, we bring up the attributes inspector on the library template object. We fill in a summary. And you can see that that reflects in the library next to our view. If I fill in the description field and the bottom documentation portion of the library, our text will show up there and the users will have a great summary of what your view or control does. So if we could go back to the demo machine.
( Period of silence )
Okay, so the first thing we need to do is get undo and redo working. So I'm gonna go ahead and open my integration class. And we see that my IB populate key paths method is there, but it, all its doing is calling super right now. So whenever our shape view is dragged out onto the design surface, the only attributes that Interface Builder is gonna know about are those of NS view. So we need to change that.
( Period of silence )
So I'm gonna go ahead and from my demo monkey, pull off a line of code here. And we see that we're calling super, so we're getting all of the properties from NS view. And then we're adding the key paths for all of the properties that are shape view supports. Number of points, background color, fill color, etcetera. So I'm gonna go ahead and save that. build and run.
( Period of silence )
Switch back to Interface Builder. And I'm gonna open our demo file. And bring up the attributes inspector.
( Period of silence )
Change that one to green, make this one a square. Rotate that one a bit. Give it a nice, oh that's very chunky. Nice thick line. And because I've implemented the populate key paths method, all of those things are undoable and redo able.
( Applause )
( Period of silence )
( Period of silence )
And like I mentioned earlier, internally we use IB to build IB. This is a great example of that. So I wanna set the drag view for my shape view.
Oops. Shape, so I'm gonna drag a shape view out into the library nib. And I want squares that are someone shout out a color.
(Unclear).
( Laughter )
Orange, thank you. And gosh, that's tiny. People don't wanna work with little shapes, they wanna work with big shapes.
So now I'm going to select my library template object. Bring up the connections inspector and I'm gonna drag from this well here, drag view to my shape view. So great, now when we drag the shape view off of the library, we'll get that nice animation, we'll see our shape view go from the tiny version that's in the library to this nice large orange square. And it'll deposit a fully configured appropriately sized version of our shape control right into the design surface. So okay, two more things missing. We don't have any, boy, that's descriptive. Let's fix that. So I'm gonna select my library template object.
( Period of silence )
( Period of silence )
The summary field, so great. What's a shape view? Well it's a view for displaying shapes. I'm not a poet, but I try. And I'm gonna fill out the description. The shape is a custom view that displays various shapes, super good. One more thing I can do is that blue square. That's not so good. Let's actually whack that. Pull in a real shape view. Give it our orange fill color.
( period of silence )
appropriately size it and I'm gonna go ahead and save my library nib. So I'm done with that. I've filled out my description. I filled out my summary. I set up a drag view. I'm done with IB. I'm gonna go ahead and quit.
- Still no label.
- Thank you.
( period of silence )
Now I'm done, thank you audience member. ( laughter ) So I'm gonna quit Interface Builder, go back to my plug in project, build and run and let's see what I hath wrought. Hey, there we go. My shape view is actually an orange square.
( Applause )
It's got the description and sample label that I set up. And when I pull it off, it's appropriately sized. And colored.
( Applause )
( Period of silence )
What, whoa!
( Laughter )
All right, so I added undo and redo support and as I mentioned Interface Builder keeps track of all the properties in your object via key value observing. So all we have to do to get unlimited undo and redo support to work is just add the correct attribute key paths in our integration category. IB will know to watch those properties for changes, dirty the document, enable undo and redo.
And the last thing we did was we polished up our library nib. We set the drag view. We didn't set the represented object because we're actually using a view. So that we got a fully configured, appropriately sized view to drag off of the library and into our design surface. And then we set the summary and description.
So that's actually it for today, we're done. That was building a plug in. so what did we cover? We covered what plug ins do. they integrate your content into the Interface Builder library, into the inspector stack. Who should write them? Well, anyone who's writing a bunch of custom views or controls being reused in a lot of places, you're definitely a candidate for writing an IB plug in.
If you're working with one custom view and one project, this is probably honestly a little bit of overkill. We talked about the architecture of the IB plug ins. All the different files you'll need to touch, inspectors, inspector subclasses, plug in sub classes, library nibs. And we ran you through a quick demo building a plug in where we talked about configuring a library nib, building inspectors for your views, the two integration classes at a minimum you'll need to support. And putting on those final, polishing touches, pardon me. So, that concludes our presentation today. If you've got anymore questions, please contact Matthew Formica, that's [email protected]. Matthew's our developer tools evangelist. And of course, if you go to developer.apple.com/wwdc/attendee, there's documentation, sample code and other resources available.