Carbon applications use all of the same string, image, sound, and video resources that Cocoa applications use. Carbon applications also support the use of nib files for loading the application’s user interface. Unlike Cocoa applications, however, Carbon applications typically do not instantiate all of the objects in a nib file at once. Instead, applications load individual windows and menus from one or more nib files at different points in the program. This chapter provides examples of how to load nib files containing Carbon objects.
Note: Carbon supports the loading of nib files through Interface Builder Services, which is part of the HIToolbox in the Carbon framework (Carbon.framework
). For information about the functions in Interface Builder Services, see Interface Builder Services Reference.
Nib File Design Guidelines
Loading Objects from Nib Files
When creating your Carbon nib files, keep the following guidelines in mind:
Store only launch-related resources in your application’s main nib file. The main nib file should contain the application menu bar and any resources that are needed at launch time only. Other resources should be stored separately.
Store frequently used user-interface components (such as document windows) in their own separate nib files. This nib file should contain only the resources needed immediately by that component.
Store infrequently used user-interface components (such as alert panels) in separate nib files. Avoid storing infrequently used components in nib files with frequently used components. When a nib file is loaded, the data for the entire file is loaded into memory and objects are instantiated from that data as needed. Thus, if an object is not used it is still occupying space in memory.
There are three main ways to load objects. You can:
Load a menu bar and main window from your application’s main nib file.
Load objects from an auxiliary nib file in the main bundle.
Load objects from nib files in other bundles.
In this section, you’ll find steps and code examples for each technique.
When your application starts up, you need to call Interface Builder Services functions to open the main nib file and unarchive the interface objects that should be open after startup. The main nib file should contain only those items that are essential when your application starts up. In most cases, the main nib file should contain only the menu bar and perhaps a main window.
The steps below outline how to open a main nib file and unarchive the objects in it. Listing 5-1 shows how to implement the steps for a nib file that contains a menu bar and a main window. If your application needs only one of these objects at startup, you can easily modify the sample code.
Call the function CreateNibReference
to create a reference to the main nib file.
Unarchive the menu bar from the main nib file by calling the function SetMenuBarFromNib
. This function also sets the menu bar so users can use the menu bar when your application has started up.
If your application has a main window, call the function CreateWindowFromNib
to unarchive the main window.
After you have unarchived the objects from the main nib file, dispose of the nib reference by calling the function DisposeNibReference
.
The function CreateWindowFromNib
unarchives the window so that it is hidden. If you want the window to be visible, you must call the Window Manager function ShowWindow
.
It is good practice to check for errors each step of the way, as shown in Listing 5-1. If the main user interface cannot be created, your application should halt the start up process and exit. This example assumes that the name of your application’s main nib file is main.nib
.
Listing 5-1 Unarchiving the menu bar and main window from the main nib file
int main (int argc, char* argv[]) |
{ |
IBNibRef nibRef; |
WindowRef window; |
OSStatus err; |
// Create a nib reference to a nib file. |
err = CreateNibReference (CFSTR ("main"), &nibRef); |
// Call the macro require_noerr to make sure no errors occurred |
require_noerr (err, CantGetNibRef); |
// Unarchive the menu bar and make it ready to use. |
err = SetMenuBarFromNib (nibRef, CFSTR("MainMenu")); |
require_noerr (err, CantSetMenuBar); |
// Unarchive the main window. |
err = CreateWindowFromNib (nibRef, CFSTR("MainWindow"), &window); |
require_noerr (err, CantCreateWindow); |
// Dispose of the nib reference as soon as you don’t need it any more. |
DisposeNibReference (nibRef); |
// Make the unarchived window visible. |
ShowWindow (window); |
// Start the event loop. RunApplicationEventLoop is a |
// Carbon Event Manager function. |
RunApplicationEventLoop (); |
// You’ll jump to one of the “Cant” statements only if there’s |
// an error. |
CantCreateWindow: |
CantSetMenuBar: |
CantGetNibRef: |
return err; |
} |
For most applications, it is useful to factor your application’s interface objects into several nib files. The main nib file should contain at the most, the menu bar and the window that opens (if any) when your application starts up. Document windows, palettes, toolbars, contextual menus, and other interface objects should be stored in separate nib files.
The steps for opening an auxiliary nib file and unarchiving an object from it are similar to those used for your main nib file:
Call the function CreateNibReference
to create a reference to the auxiliary nib file that contains the object you want to unarchive.
Call the appropriate function to unarchive the object from the nib file. To unarchive a window, call the function CreateWindowFromNib
; to unarchive a menu, call the function CreateMenuFromNib
.
After you have unarchived the object from the auxiliary nib file, dispose of the nib reference by calling the function DisposeNibReference
.
One common use of an auxiliary nib file is to store an object that’s used repeatedly in an application, such as a document window. Another use is to store objects that are rarely needed, such as an About window. Listing 5-2 shows how to implement a MyCreateNewDocument
function that your application would call each time the user creates a new document. The code uses macro-based error checking to abort the operation if an error occurs.
Listing 5-2 Unarchiving a document window from an auxiliary nib file
WindowRef MyCreateNewDocument (CFStringRef inName) |
{ |
IBNibRef documentNib; |
OSStatus err; |
WindowRef theWindow; |
// Create a nib reference to an auxiliary nib file with |
// the name document.nib. |
err = CreateNibReference (CFSTR ("document"), &documentNib); |
// Call the macro require_noerr to make sure no errors occurred |
require_noerr (err, CantGetNibRef); |
// Unarchive the document window. Use the name you gave to the |
// window object in the Instances pane in Interface Builder. |
err = CreateWindowFromNib (documentNib, CFSTR("MyDocument"), |
&theWindow); |
require_noerr (err, CantCreateWindow); |
// Dispose of the nib reference as soon as you don’t need it anymore. |
DisposeNibReference (documentNib); |
// Call the Window Manager function to set the title shown in the |
// window’s title bar to the name passed to MyCreateNewDocument. |
err = SetWindowTitleWithCFString (theWindow, inName); |
// In this example, the window gets returned. Remember, it’s been |
// unarchived, but it is still not visible. It won’t be visible |
// until you call the Window Manager function ShowWindow. |
return theWindow; |
// You’ll jump to one of the “Cant” statements only if there’s |
// an error. |
CantCreateWindow: |
CantGetNibRef: |
return NULL; |
} |
Your application is not limited to using interface objects contained within its own bundle. You can unarchive interface objects from another bundle or framework to which your application has access. For example, you could unarchive a tools palette or other object provided by a plug-in bundle.
The steps for unarchiving an object from a nib file in a framework or other bundle are similar to those used to open an auxiliary nib file and are listed below. The main difference is that you must first create a a reference to the external bundle. You must also call the function CreateNibReferenceWithCFBundle
instead of CreateNibReference
to create a reference to the nib file. The steps are as follows:
Call the Core Foundation URL Services function CFURLCreateWithFileSystemPath
to create a URL that points to the desired bundle. (For reference documentation, see CFURL Reference.)
Call the Core Foundation Bundle Services function CFBundleCreate
to create a reference to the bundle that contains nib file you want to open. (For reference documentation, see CFBundle Reference.)
Call the function CreateNibReferenceWithCFBundle
to create a reference to the nib file that contains the object you want to unarchive.
Call the appropriate function to unarchive the object from the nib file. To unarchive a window, call the function CreateWindowFromNib
; to unarchive a menu, call the function CreateMenuFromNib
.
After you have unarchived the object from the nib file, dispose of the nib reference by calling the function DisposeNibReference
.
The function MyCreateWidgetFromFramework
, shown in Listing 5-3, shows how to unarchive a “widget window” from a bundle whose path you pass to the function.
Listing 5-3 Unarchiving a widget window from a nib file in a bundle
WindowRef MyCreateWidgetFromBundle (CFStringRef widgetBundlePath |
CFStringRef widgetFileName, |
CFStringRef widgetWindowName) |
{ |
IBNibRef widgetNib; |
OSStatus err; |
WindowRef theWindow; |
CFBundleRef mainBundle; |
CFURLRef bundleURL; |
CFBundleRef widgetBundle; |
// Look for a resource in the bundle passed to |
// the function MyCreateWidgetFromBundle |
bundleURL = CFURLCreateWithFileSystemPath( |
kCFAllocatorDefault, |
widgetBundlePath, |
kCFURLPOSIXPathStyle, |
TRUE); |
// Make a bundle instance using the URL Reference |
widgetBundle = CFBundleCreate (kCFAllocatorDefault, bundleURL); |
// Create a nib reference to the nib file. |
err = CreateNibReferenceWithCFBundle (widgetBundle, |
widgetFileName, &widgetNib); |
// Call the macro require_noerr to make sure no errors occurred |
require_noerr (err, CantGetNibRef); |
// Unarchive the widget window. |
err = CreateWindowFromNib (widgetNib, widgetWindowName, &theWindow); |
require_noerr (err, CantCreateWindow ); |
// Dispose of the nib reference as soon as you don’t need it anymore. |
DisposeNibReference (widgetNib); |
// Release the Core Foundation objects |
CFRelease (bundleURL); |
CFRelease (widgetBundle); |
// In this example, the window gets returned. Remember, it’s been |
// unarchived, but it is still not visible. It won’t be visible |
// until you call the Window Manager function ShowWindow. |
return theWindow; |
// You’ll jump to one of the “Cant” statements only if there’s |
// an error. |
CantCreateWindow: |
CantGetNibRef: |
return NULL; |
} |
© 2009 Apple Inc. All Rights Reserved. (Last updated: 2009-01-06)