Creating nib documents Adding objects to a nib document Confi guring and connecting objects together Defi ning and creating custom objects Customizing Interface Builder Interface Builder i
Trang 1Interface Builder
WHAT'S IN THIS CHAPTER?
Creating nib documents Adding objects to a nib document Confi guring and connecting objects together Defi ning and creating custom objects Customizing Interface Builder Interface Builder is a graphical user interface editor Interface Builder and the Xcode IDE work hand in glove to create a fl uid, dynamic, and (nearly) seamless workfl ow for designing and implementing your user interface objects Getting the most out of Interface Builder is essential
to any Mac or iPhone development project
Interface Builder has a long history Interface Builder and Project Builder (later renamed Xcode) trace their lineage all the way back to NeXT, where they were originally conceived
Twenty years later, the roles of these two applications remain largely unchanged — a testament to the vision of its creators You write your code (controller) in Xcode using text editors and compilers You design your interface (view) in Interface Builder using graphical design tools and object inspectors
Although this is not a book about programming, it ’ s very diffi cult to describe how to use Interface Builder without understanding what Interface Builder does and the technologies that allow it to work This is a common source of confusion for new developers, particularly those coming from other development environments If you fall into this category (or don ’ t know whether you fall into this category), read through the sections “ What Is Interface Builder? ” and “ Interface Builder Workfl ow ” Readers comfortable with Interface Builder concepts can skip ahead to the sections that describe specifi c features
➤
➤
➤
➤
➤
Trang 2230 ❘CHAPTER 13 INTERFACE BUILDER
WHAT IS INTERFACE BUILDER?
In a nutshell, Interface Builder, shown in Figure 13 - 1, edits a graph of archived objects stored in
a data fi le That ’ s a terse statement, but it accurately captures the key concept behind Interface
Builder Specifi cally, Interface Builder edits the contents of a nib document A nib document
contains archived objects — also called serialized, marshaled, or freeze - dried objects The nib
document is transformed into a nib fi le when the project is built At run time, you “ load ” a nib fi le;
this un - archives (de - serializes, un - marshals) the graph of objects, creating instances of objects with
preset properties, indistinguishable from objects created programmatically
NIB originally stood for NeXT Interface Builder document, but Apple has offi cially rechristened the extension Interface Builder Document Although modern nib documents are actually XIB (XML Interface Builder) fi les, the terms “nib,” “nib fi le,” and “nib document” are used genetrically to describe all Interface Builder documents, regardless of their actual format The term
“nib document” is used here when talking about the document fi le (or bundle) that you edit in Interface Builder, while “nib fi le” usually refers to the binary deployment fi le loaded by your application.
FIGURE 13-1
By editing an archived data fi le, Interface Builder allows you to defi ne complex graphs of
interconnected objects, customize them in a myriad of ways, and do all of that using visual design
tools At run time, the entire set of objects is instantiated, initialized, and connected together with
a single code statement — or no code at all, for nib fi les loaded automatically by the framework
This improves your productivity and the robustness of your applications in a number of ways:
Your application code is less brittle because, simply, there ’ s less code — sometimes no code at all
It ’ s easier, faster, and more rational to create an interface design using a graphical design tool rather than hard - coding values in your program Should the coordinates of your input text fi eld be (314,20,276,22) or (20,314,22,276)?
➤
➤
Trang 3NIB fi les are more effi cient An archived object data stream is generally far more compact than the code required to create, initialize, confi gure, and connect that same set of objects
Changes to your interface often don ’ t require any code changes This minimizes debugging and reduces the chance of introducing unexpected errors
Your interface can be redefi ned based on the location and language of your user, or for any other reason you choose Multiple nib fi les that represent the same, or similar, interfaces can be dynamically selected at run time to change the look and feel of your application
The operating system automatically loads the correct nib fi le for your user ’ s language and locale You can selectively load nib fi les programmatically based on any criteria you defi ne
Almost as important as what Interface Builder is, is what Interface Builder is not:
Interface Builder is not a template editor
Interface Builder is not a code generator
Interface Builder is not a compiler
If you ’ ve come from a development environment where the graphical user interface design tools create scripts, layout information fi les, generate source, or insert binary code into your application, set those concepts aside Interface Builder edits archived objects, or specifi cally data, that just happens to describe objects Everything you do in Interface Builder will be from the perspective of objects, their properties, and their relationships — the same way you design with objects in your code The result (the nib fi le) is just data It ’ s data during development; it ’ s data at build time; and
it ’ s still data in your fi nished application Only when the data is un - archived does it become objects
in your application
Code vs Interface Builder
To provide an unambiguous example, consider the following two programs The fi rst program, shown in Listing 13 - 1, creates a window and populates it with some controls
LISTING 13 - 1: Creating a Window Programmatically
- (void)makeNewRecordWindow {
NSRect frame = NSMakeRect(100.0,100.0,349.0,123.0);
newRecordWindow = [[NSWindow alloc]
initWithContentRect:frame styleMask:(NSTitledWindowMask|
NSClosableWindowMask|
NSMiniaturizableWindowMask) backing:NSBackingStoreBuffered defer:YES];
NSView* windowContentView = [newRecordWindow contentView];
frame = NSMakeRect(253.0,12.0,82.0,32.0);
NSButton* okButton = [[NSButton alloc] initWithFrame:frame];
[okButton setTitle:@"Create"];
[okButton setButtonType:NSMomentaryLightButton];
➤
➤
➤
➤
➤
➤
continues
Trang 4232 ❘ CHAPTER 13 INTERFACE BUILDER
LISTING 13-1 (continued)
[okButton setBezelStyle:NSRoundedBezelStyle];
[windowContentView addSubview:okButton];
frame = NSMakeRect(171.0,12.0,82.0,32.0);
NSButton* cancelButton = [[NSButton alloc] initWithFrame:frame];
[cancelButton setTitle:@"Cancel"];
[cancelButton setButtonType:NSMomentaryLightButton];
[cancelButton setBezelStyle:NSRoundedBezelStyle];
[windowContentView addSubview:cancelButton];
frame = NSMakeRect(20.0,90.0,130.0,13.0);
NSTextField* titleField = [[NSTextField alloc] initWithFrame:frame];
[titleField setStringValue:@"Record Name:"];
[titleField setEditable:NO];
[titleField setSelectable:NO];
[titleField setBordered:NO];
[titleField setDrawsBackground:NO];
[windowContentView addSubview:titleField];
frame = NSMakeRect(20.0,60.0,309.0,22.0);
NSTextField* nameField = [[NSTextField alloc] initWithFrame:frame];
[windowContentView addSubview:nameField];
[newRecordWindow makeKeyAndOrderFront:self];
}
The Interface Builder document that creates an identical window was shown in Figure 13 - 1
The code needed to create, initialize, and display the window defi ned by the nib document shown
in Figure 13 - 1 is shown in Listing 13 - 2
LISTING 13 - 2: Creating a Window Stored in a Nib File
- (void)makeNewRecordWindow
{
[[NSBundle mainBundle] loadNibNamed:@"NewRecord" owner:self];
[newRecordWindow makeKeyAndOrderFront:self];
}
The two different - makeNewRecordWindow methods, shown in Listing 13 - 1 and 13 - 2, accomplish
exactly the same thing After the method returns, the objects that are created, their relationships,
properties, and inter - object references are the same
It should be obvious that the window design in Figure 13 - 1 is far easier to comprehend and
manipulate than the code in Listing 13 - 1 For example, a button object could be repositioned simply
by dragging it to a new location This is vastly simpler, and more predictable, than trying to edit the
coordinate constants in Listing 13 - 1 — assuming you could fi nd them
This brings me to one last, but important, benefi t of using Interface Builder:
Your application doesn ’ t give up any control or features by using nib created objects You are free to programmatically manipulate objects created by a nib fi le just as you would
➤
Trang 5objects created programmatically You can defi ne as much, or as little, in the nib fi le
as appropriate Many nib fi les defi ne nothing more than a container object that ’ s later populated programmatically
The Three C ’ s of Interface Builder
Interface Builder lets you do three things:
Create instances of objects Confi gure object attributes Connect objects together You can create instances of any of the multitude of predefi ned objects provided in Interface Builder ’ s library, or you can create instances of classes that you ’ ve defi ned yourself Creating objects is described in the section “ Creating Objects ”
You edit the attributes (properties) of object instances in a variety of ways, but the result is ultimately the same; the property values you select become part of the archive data stream and are used to initialize the object when it ’ s created at run time This is covered in the sections “ Selecting Objects ” and “ Confi guring Objects ”
Finally, and probably what Interface Builder is most famous for, is the ability to connect objects.
A connection is just IB - speak for an object reference In Interface Builder, you make a connection
by dragging an outlet or action from one object to another At run time, the connection sets
an instance variable of the referring object to point to the object that you connected it to It ’ s that simple The effect of connecting the outlet inputField to an NSTextField object would be equivalent to writing the code:
self.inputField = [NSTextField new];
You can learn the many different ways of connecting objects in the section “ Connecting Objects ” That ’ s it! That ’ s all Interface Builder does With the mystery of Interface Builder out of the way,
I can now show you how Interface Builder integrates into Xcode and your development workfl ow
INTERFACE BUILDER WORKFLOW
Interface Builder is (technically) a standalone editor You can launch Interface Builder and use it to create, edit, and save nib documents Except in a few rare cases — say where you might want to use Interface Builder to “ hack ” an existing nib document — you ’ re most likely to use Interface Builder
as an adjunct editor for an Xcode project
Editing NIB Documents in an Xcode Workfl ow
The typical workfl ow when using Xcode and Interface Builder is shown in Figure 13 - 2
➤
➤
➤
Trang 6234 ❘CHAPTER 13 INTERFACE BUILDER
Interface Builder isn ’ t a compiler, but it does observe and interpret your project ’ s class declarations
It understands the classes, inheritance, properties, and methods that you declare and synchronizes
those with your nib document Your development workfl ow might proceed like so:
1. Xcode: Defi ne a new view controller class
2. Interface Builder: Create a nib document to defi ne the objects in the interface
3. Interface Builder: Add some input text fi eld objects to the interface
4. Xcode: Add some instance variables to the view controller class that will refer to those input
fi eld objects
5. Interface Builder: Connect the input fi eld objects to the instance variables
6. Xcode: Create an action method
7. Interface Builder: Add a button to the interface and connect its action to the controller ’ s
new method
8. And so on
FIGURE 13-2
Trang 7As you can see, you ’ ll jump back and forth between Xcode and Interface Builder quite a lot while working on your interface A number of features and shortcuts for making this workfl ow nearly seamless are covered at appropriate places in this chapter
Simulating an Interface
During interface design and development, you ’ ll often want get an approximate idea of how your interface will look and behave Building and running your application is the obvious way to test
it, but sometimes that ’ s not convenient; projects under development are often in a state where they can ’ t be built and tested
Interface Builder provides an interface simulator, which you can launch using the File ➪ Simulate Interface (Command+R) command The simulator loads your nib document in a neutral application environment consisting only of the standard framework objects supplied by the operating system All custom objects, outlets, and actions are reduced to their base class behavior or are ignored
Figure 13 - 3 shows an iPhone interface design and the same nib document running
in the iPhone simulator Interface Builder uses the iPhone simulator for Cocoa Touch documents Cocoa documents are presented
in a Cocoa simulator built into the Interface Builder application When you ’ re done with the simulation, choose the Quit command
The simulator presents your interface using the standard framework objects, sans any programmatic enhancements provided by your application The results can be quite rich or stunningly dull Consider
a custom view object that ’ s drawn by your application; the simulator will present a blank white square The simulator provides canned data for list, table, and browser views (the names of cities, in the example shown in Figure 13 - 3) Editable text fi elds are editable; date pickers are pickable; and so on
The simulator is good for checking window resizing behavior, multi - tab views, table column resizing, and the like Most buttons and application - specifi c menu items will be non - functional, of course
Some interface objects can automatically record position and other state information in the user defaults for your application For example, the NSWindow object can record its position and size when closed and a check box button can be bound to a user defaults property The next time the application/simulator is launched, the position of the window and the state of the button will be restored from the user defaults
FIGURE 13-3
Trang 8236 ❘CHAPTER 13 INTERFACE BUILDER
Interface Builder provides a “ scratch pad ” user defaults fi le for each simulated nib document This
transient set of preferences can be set to be periodically, or manually, erased from the Simulator tab
of the Interface Builder preferences Erasing the preferences clears all user default values, as though
the application was being run for the fi rst time
Building Your Project from Interface Builder
If you look at the workfl ow diagram in Figure 13 - 2, you ’ ll see that it ’ s very typical to write code, make
connections in Interface Builder, switch back to Xcode, and then build and test your application
Interface Builder provides a shortcut: the File ➪ Build and Go in Xcode (Shift+Command+R)
command switches back to Xcode, builds your project, and launches it
INTERFACE BUILDER ’ S INTERFACE
This section starts with a brief tour of Interface Builder ’ s interface One reason it will be brief,
and also one of the reasons Interface Builder is so easy to use, is that there are basically only
three interface elements: the nib document window, the inspector palette, and the library palette
All three are shown in Figures 13 - 4 and 13 - 5
FIGURE 13-4