OOFILE | Downloads | Purchasing | Press | Services | Company Information | Soapbox | References | F.A.Q. | HOME 



Why yet another FAQ?

This is my learning curve and as a professional developer of 20+ years experience, 10+ on Mac, it shows the issues I dealt with in order.

It also reflects a PowerPlant and traditional OO background, unlike many other Cocoa developers.

I wrote it to support my learning curve and I like to publish stuff that I think people might find useful.

It is not as polished or organised as I'd like but I figured anyone looking for useful stuff and finding this would at least appreciate the information being published and I really don't have the time for the next few months to do more.

The main project which was my Cocoa learning curve was a server and information presentation cross-platform tool including drawing OpenGL, histogram and scrolling line graphs using source shared with a Windows and PocketPC version. (Brainwave software now shipped with the personal brainwave devices from http://www.ibva.com/)

Please mail corrections, praise, criticism, virtual chocolate:

last updated August 7th 2003


Important Docs that are hard to find

Roles of objects that appear in the Interface Builder window like File's Owner and First Responder are covered under LoadingResources, specifically:



How do I create a new nib file for a new window given an existing project open in Project Builder and a MainMenu.nib open in Interface Builder?

Choose File - New in Interface Builder and select Empty as the file type. When you save it you are asked if you want to add it to the project. You can either create an NSDocument or NSWindowController subclass in PB and set it to be the Files Owner of the new nib file.

To link the new class from its perspective to the nib, if you are subclassing NSDocument, override the method windowNibName returning the nib file name, or in its init use [super initWithNibFileName:@"MyClass"]

see Hillegass p 149-152 & Q29

How do I set Files Owner in a Nib file?

Make sure your header file has been saved - there is no prompting!

Import the class definition (or update it) into the nib file using Classes - Read Files and select the header.

Click on Files Owner and choose Tools - Show Info (shift-command-I). Choose Custom Class from the popup at the top of the Files Owner Info panel and scroll down until you see your class. WARNING do NOT double-click on Files Owner, you will be taken to the info for the Class not the Instance, and the Custom Class list will be blank.

Now set the reverse - control-drag from the Files Owner to the Window and double-click the 'window' outlet. (Hillegass Figure 7.15, p 150)

See: Q7
How do I get a non-document window to appear

Can I check a nib file into CVS? It doesn't have a CVS status in PB.

If you add the cvswrappers from from /Developer/Tools to the CVSROOT directory, nibs will be included in a COPY mode.

Is there a convention for the tag names?

doesn't seem to be, and they are mainly used under Carbon, Cocoa uses direct connection to Action methods.

Is there a way to see all incoming connections to an object? eg: if I connect the Preferences menu item to an AppController, I can see the connection from the menu item but not the AppController's point of view.-

Click on the list view in IB to see incoming and outgoing connections.

When do I need to declare a method and when not?

If it is a method declared by a parent, you don't need to declare it. (eg: init, dealloc)

How do I get a non-document window to appear

Either 1) in an action method of your NSWindowController class, [self showWindow:sender]

Putting [self showWindow:nil] in the init method also works if you want the window to appear as soon as the instance is created.

or 2) in an separate class, an action method that creates it (eg: AppController in Hillegass p 145) you need to do
[yourWindowController showWindow:self]

Note if you mistakenly put something like [self showWindow] in your AppController class you will get a warning from PB that your class doesn't implement the method showWindow.

or 3) Apple's SimpleMultiWindow sample:

- (IBAction)displaySecondWindow:(id)sender
    if (_controller == nil) // Check to see if we've already loaded the second window controller
        // If not, instantiate a new controller. The controller is told to initWithWindowNibName. The
        // new instance will use NSBundle to find and load the correct SecondWindow.nib file. When
        // the nib is loaded, the resultField outlet described in SMWSecondWindow.h will be filled.
        _controller = [[SMWSecondWindowController alloc] initWithWindowNibName:@"SecondWindow"]; 
    //Now that we have a controller, tell it to show the window.
    [_controller showWindow:self];

How do I get keydown/up events?

Given a window, eg: non-document window like in Q7, your NSWindowController subclass will receive events as the FirstResponder for that window, when frontmost.

Simply provide implementations for -(void)keyDown:(NSEvent*) and -(void)keyUp:(NSEvent*) you can then call [theEvent keyCode] to get the actual key code.

Even when a view within your window becomes the FirstResponder, your window controller remains on the responder chain and so, unless a view further down the chain overrides keyUp to swallow the event, you will still have your event method called.

Why would I draw with NSBezierPath vs NSRectFill, NSLayoutManager etc.?

See the Sketch demo SKTTextArea for an example when the drawing involves text or an NSImage (like SKTImage). Otherwise, try to create an NSBezierPath.

See also Q42 discussion of fast drawing.

How do I put a view in a window so that the WindowController (ie: Files Owner) of the window can communicate with the custom view?

See Hillegass p226 on In Interface Builder

  • select Classes tab
  • select NSView in the list of classes
  • choose Classes - Subclass NSView
  • name youre view (eg: AndyView
  • choose Classes - Create Files for AndyView
  • make sure the file browser that appears points to your project root or suitable subdir and the project is checked in the Insert Into Targets list on the save dialog

in Interface Builder, to add your custom view to a window

  • make the Window visible
  • click on the Cocoa-Containers panel in the Palettes window (icon is a tab panel, the 6th along)
  • drag a CustomView onto the window
  • resize as desired
  • bringup the Info panel for your Custom View
    • choose Size to be able to set how it resizes with the containing screen<
    • set the CustomClass for the view to be your new view (AndyView)

to link the view so it is programmatically addressable from the window controller:

  • add an outlet member variable to the controller, eg: IBOutlet AndyView* importantView;
  • save these changes
  • in Interface Builder:
    • reimport the class definition by Classes - Read Files
    • control drag from the view to the instance of the window controller, then double-click the matching outlet you created above

How do I init an NSString from a wchar_t*?

[NSString localizedStringWithFormat:@"%S", inStr] the capital S means take a string arg of 16bit chars will work if sizeof(wchar_t)==2

Otherwise, copy your wchar_t array to an array of unichar and use the above or [NSString initWithCharacters:length:]

How do I add a framework to CodeWarrior (Pro 8)?

See Mach-O_Notes.txt in the CodeWarrior release notes.

First make sure it is in the right place - it appears you can only add frameworks from within /System/Libraries/Frameworks or similar dirs, not arbitrary locations.

What does it mean when my app looks like a folder icon?


You need to rebuild your app from scratch with CW? I think it means that the info.plist didn't get built correctly or that CW failed to copy an icon (this may be CW Pro 8 bug).

What does it mean when I get error -39 or just quit when run the debugger (from NSApplicationMain function call) when run from CodeWarrior?

You have not included a .plc file to generate the info.plist and finish the bundling job. Thus, the bundle doesn't know what nib file to load (see A16 for related Document discussion).

How do I create a Document-based application from a plain App, so it is equivalent to starting from the Document stationery?

The key to making a Document-based application is having a Document Type in the plist, which describes the Document and specifies the class. That's how the instantiation of your document occurs.

You will also need to connect up all the traditional File actions to FirstResponder, that's done for you using the Document stationery.

Adding actions of your document to be triggered by menu items is a royal pain - you have to copy the actions across and add to the First Responder in the MainMenu.nib

Create the Document nib file and set its files Owner to your custom Doc class.

Easiest way to copy Actions is to have the Document and MainMenu nib files open so you can see the custom Document class in the Classes tab - using the Attributes tab of the info panel will let you double click an Action and copy its name. Then click on FirstResponder in the MainMenu.nib and Add an action, pasting in the name.

This could have been made vastly easier by being able to just drag the Actions across between two info panels but there doesn't seem to be a way to pin panels open.

How do I get an instance of my Document created at application startup?

Have an entry of Document Type in the plist for your custom document class and ensure there is no initial window created by the initial nib (eg: remove the Hello World window created by the CodeWarrior Application stationery)

All other bits from the Document stationery govern behaviour, not whether the Document is loaded.

If there are multiple Document types, what is instantiated at application startup?

A single document instance is created for the first Document Type. Note that if you are experimenting with changing the Document Types, Project Builder seems to need you to Clean the project in order to recognise the change. This can lead to some confusion about how the process works if you just change the list of types and save the project.

Why would I want a Document subclass?

Because you have a central data model which needs an object to manage it.

What do I do differently if I want my Document subclass to just coordinate an in-memory data model, maybe a database connection, but not a local physical file?


Put the following in your NSDocument subclass.

- (NSData *)dataRepresentationOfType:(NSString *)aType
   return nil;

- (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType
   return YES;

In terms of handling File menu commands, my simple approach was just to wire the File menu to my own commands but more is likely required to be scriptable.

How do I have a Document subclass which doesn't display any windows?

Start with a normal Cocoa Document app stationery: - remove the MyDocument.nib file - remove the methods windowNibName & windowControllerDidLoadNib from MyDocument.

Without a nib file and without a method saying to load it (the key point) your Document is still created at application startup (breakpoint in the MyDocument init method to confirm). If there is no current window, an instance of the document is also created every time you activate the application by clicking on it in the Dock.

Does the Cocoa Stationery for CW Pro 8 create a Document-based App?

No, it's the equivalent of the PB simple Application and so needs a lot of work. Copy the sample application instead.
(see also A15 if you've already created your non-Document app and want to fix it)

Where are the plist entries stored that are visible in ProjectBuilder's Target panes?

XML format inside the PB bundle, in the pbxproj file, which is editable in BBEdit eg: MindforceBG/MindforceBG.pbproj/project.pbxproj

How do I convert property list items such as in a .pbxproj file to the format CodeWarrior uses?

Start with the release note ...Compiler Notes/Property List Notes.txt which contains a language guide. Go through the XML tags and find the corresponding syntax in the older textual version that CW supports (which is rather easier to read).

** remember to force recompiles of property list files!

My init method in a window controller isn't being called even though my Document is creating it in the makeWindowControllers method.

Check to see WHICH init method you are calling (this is like having multiple constructors in C++). It is likely you are calling initWithWindowNibName instead of plain init.

I have a standard data file being read in a portable C++ program, how do I trigger it being read in the NSDocument?

NSDocument method - (BOOL)readFromFile:(NSString *)fileName ofType:(NSString *)docType can be overriden to totally control how loading occurs.

What is the Cocoa Equivalent of an MFC OnUpdateBlah(CCmdUI* pCmdUI) or PowerPlant FindCommandStatus?

p643 Cocoa Programming - no per-item method equivalent but there's the validateMenuItem method called for for the menu item target.

This means you need to implement a method with series of if-then actions for everything handled by that target, which is similar to FindCommandStatus:.

	- (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem {
SEL theAction = [menuItem action]; if (theAction == @selector(SomeCommandThatShouldBeChecked:)) { if (SomeConditionWantingCheckmark) [menuItem setState:NSOnState];
[menuItem setState:NSOffState];
else if (theAction == @selector(aCommandThatShouldBeDisabled:)) { return NO; } ... else return [super validateMenuItem:menuItem]; }

No, I'm not at all happy with the above answer - I would love to be told a better way!

How do I get actions into the First Responder.

Adding actions of your document to be triggered by menu items is a royal pain - you have to copy the actions across and add to the First Responder in the MainMenu.nib

Easiest way to copy Actions is to have the Document and MainMenu nib files open so you can see the custom Document class in the Classes tab - using the Attributes tab of the info panel will let you double click an Action and copy its name. Then click on FirstResponder in the MainMenu.nib and Add an action, pasting in the name.

This could have been made vastly easier by being able to just drag the Actions across between two info panels but there doesn't seem to be a way to pin panels open.

Metrowerks wouldn't have left the tool like this!

How do I get an Image into the Images tab of a nib?

With CW, add the image file to the project and the next time you launch Interface Builder you will see it in there (I suspect the same for PB).

Should I subclass NSWindow?

Generally no unless you want to change some very basic behaviours. Set something as the delegate for a Window instead (via setDelegate).

Should I subclass NSWindowController?

If you have objects in a nib file, override NSWindowController to provide mgmt.

if you want to call windowDidLoad, windowWillLoad or windowTitleForDocumentDisplayName.

When you have a second window type in an app, create a controller.

Page 152: Nibs and Controllers: a rule-of-thumb When I start an application, I have a basic process by which I create all the nibs and controller objects. I vary from this process regularly, but it is a good starting point. Some of my students have found it useful, so here it is:

1. I create a nib file for each window in my application. Then I go through the nib files creating a controller for each using the following guidelines. 2. MainMenu.nib? I create a subclass of NSObject called AppController and instantiate it. AppController is made the delegate of the NSApplication. 3. A document nib? I create a subclass of NSDocument and set the "File's Owner" to be that type. 4. Other window (Example: a find panel)? I create a subclass of NSWindowController and set the "File's Owner" to be that type.

It is OK to wander from this. Sometimes I will put multiple windows in a single nib. Other times, I will have multiple controllers for a single window. This rule is just a good starting point.

How does MVC (Model-View-Controller) apply to Cocoa?

p688 of Cocoa Programming talks about using an NSDocument sublass as the Controller, an NSObject subclass as the Model and standard Cocoa classes as the View(s).

If I add actions and outlets in Interface Builder to a class I've already written, how do I get them back into that class?

Generate the files for your class from within IB to a different directory and manually merge the files.

When I run my Document-based app I get an alert saying can't create new docment - why?

Check the .plc file to make sure the key "NSDocumentClass" value string matches your document class name.

When is a return value autoreleased?

it's always autoreleased if you're not using the +alloc method to create it or the -copy method to duplicate it. That's the universal convention, and there are no exceptions (excepting perhaps bugs in the implementation). (from http://www.cocoadev.com/index.pl?CocoaMostWanted)

Why can't I reconnect the wiring from a menu to actions - I know the actions are there on my destination object?

You have to break the connection first - see Q35.

What's a quick way to remove connections?

Looking at a connection in Show Info, you can double-click it to remove. However, if you go into the connections view (alternative view in Instances panel) you can control-click any connection to break it.

How do I get my icon in CodeWarrior 8.3?


  • Add plc entry (in your blah.plc file):
    key "CFBundleIconFile" value string "YourIconFile.icns"
  • Quit CodeWarrior or at least close the project
  • Delete the existing app
  • Launch CodeWarrior - you will see a warning you can ignore, like:
    The following access path in target “Cocoa Debug” of project “MFStatusGUIOSX.mcp” cannot be found:
    {Project}(CWBuild)/MindForceBGCW Debug.app/Contents
  • Manually compile the plc (Make doesn't recompile it).

Original tip: to avoid problems with CodeWarrior finding files in your generated app bundles, make sure your English.lproj directory is the FIRST in your access path. I tried turning off recursive access paths for the project directory but that breaks the build.

Better idea: Set your output directory to a bracketed subdir like (CWBuild).

How do you create a simple Alert, like ShowAlert?

Call NSBeginAlertSheet or one of the related functions (under Application Kit/General/Functions/Panels in Cocoa Browser).

For an even simpler message box, use NSRunAlertPanel.

          NSRunAlertPanel(@"Unable to save preferences to file", newName, nil, nil, nil);

How do you create a sheet with data entry?

The Cocoa Programming example TaskOutliner (ch 18) has methods in the Document invoking a nib with no custom controller, the Cancel and OK buttons on the nib sending closeSheet and cancelSheet actions wired to the Document as Files Owner.

Data comes back out of the sheet by having two NSTextField*'s wired to outlets in the document.

The sheet is invoked with

[NSApp beginSheet:[self sheet] modalForWindow:[outlineView window] modalDelegate:nil didEndSelector:NULL contextInfo:nil];

How do you create a floating palette for data entry?

Easiest is using Interface Builder for the whole thing - choose new and Cocoa - Attention Panel as the starting point.

Subclass NSWindowController to manage it. Add outlets to your window controller for the controls which you want to set or get data back from.

Then instantiate your window controller somewhere in an action responding to a Show method. This might be in your App, Document or related class.

The Sketch sample code has a nice approach that uses lazy loading by SKTDrawAppDelegate being responsible for all these commands, and invoking panels:

- (IBAction)showToolPaletteAction:(id)sender {
[[SKTToolPaletteController sharedToolPaletteController] showWindow:sender];

How do you get the window created by NSBundle loadNibNamed: ...

As in the sample descibed in A38 your class is the Files Owner for the nib file and the Panel in the nib file is wired back to an NSWindow* outlet so will be initialised and can be returned by a method like:

@interface ClassWhichIsFilesOwner {
  IBOutlet NSWindow* mSamplePanel;  // wire the Panel back to this outlet


- (NSWindow *)samplePanel
    if (mSamplePanel == nil) 
      [NSBundle loadNibNamed:@"YourPanelNib" owner:self];
   return mSamplePanel;

How do you get a nib back out of a built app?

Use Terminal to copy the lost nib file back out of the app, eg:

             cd blah.app/Contents/Resources
             cp -Rp MainMenu.nib /Users/andydent/dev/blah/English.lproj            

What's the fastest way to draw, eg: quickly refreshing a graph with text and lots of lines/rectangles?

NSQuickdrawView and old-fashioned Quickdraw seems quicker especially for rendering text.

I had a lot of trouble finding clear answers to this issue but it seems that otherwise text rendering is very sophisticated/heavyweight. Eric Pepke's Mac One-Liner news postings suggested using Quickdraw and my experience in graphing seems to bear it out.

It is possible that OpenGL drawing may be faster but drawing text in OpenGL on OSX at present is very painful.


Why do I sometimes crash when I've got a pointer back from a newly created window?


Painfully-learned lesson <insert scream of realization/triumph>.

Window initialisation appears to be multi-threaded. If the pointer you get back is not created in init then it will not necessarily be valid if you retrieve it immediately after window construction.

MyWindowController* _controller = [[MyWindowController alloc] initWithWindowNibName:@"MFOSXGraphFFT"];
return [_controller settings]; // unsafe!

What makes that unsafe is that settings returns a variable initialised in a deferred manner:

@implementation MyWindowController
- (void)windowDidLoad
   mSettings = [mGraphView getSettings];

Later insight - I don't think they are multi-threading here, at least not in your app. What gives the appearance of multi-threading is lazy construction. If you call [myWindowController window] then you force your window nib to be loaded and windowDidLoad will be invoked. Otherwise you are waiting for Aqua to do a refresh and instantiate that window.

eg: here's a piece of code that retains a window list for later closing a subset of windows.

- (void) FinishCreatingGraphWindow:(MFGraphWindow*)inController
   NSWindow* pWindow = [inController window];  // force windowDidLoad to be called
   NSCAssert(pWindow!=nil, @"Should have a window so we can listen for it closing");
   [ [NSNotificationCenter defaultCenter] addObserver:self 

How do I setup my CodeWarrior precompiled headers to cope with both .mm and .m files?


If your project has both .m and .mm files you can't have just one precompiled header, you have to have two because one is Objective-C and the other is Objective-C++ and compiles C++ code and applies C++ mangling to other functions (unless they are inside extern "C").


// put MyPrefix.h in the CodeWarrior C++ settings Prefix File
#if __option (dont_inline)  // assume good indicator of debug mode
   #ifdef __cplusplus
     #include "./Debug MyCocoaHeaders++Mach-O"
     #include "./Debug MyCocoaHeadersMach-O"
#else  // non-debug
   #ifdef __cplusplus
     #include "./MyCocoaHeaders++Mach-O"
     #include "./MyCocoaHeadersMach-O"



#if __option (dont_inline) 
   #pragma precompile_target "Debug MyCocoaHeadersMach-O"
   #pragma precompile_target "MyCocoaHeadersMach-O"
#include "MyCommonHeader.h"



#if __option (dont_inline) 
   #pragma precompile_target "Debug MyCocoaHeaders++Mach-O"
   #pragma precompile_target "MyCocoaHeaders++Mach-O"
#include "MyCommonHeader.h"



#if __option (dont_inline) 
   #define DEBUG  1 // our flag, standard in Windows code, also used in OSX CarbonCore/Debugging.h
   #define NDEBUG  // disabled assert()
#pragma c99 on
#pragma once on
#include "CocoaHeaders.m" // standard MW header


Why doesn't my Window appear after editing the nib file?


Check that the Files Owner is still an NSWindowController subclass and that it has the window outlet connected.

One scenario in which I managed to break this connection was where my subclass had been refactored so I had another class between it an NSWindowController. Importing the new definition broke the connection and even after the new parent was imported, so Interface Builder knew that my Files Owner was an NSWindowController, it didn't reconnect. There is a warning dialog when you read files in this kind of circumstance - take it seriously and check all connections after. I ignored the warning because I thought it was just about changes to Actions.


How do I check what modifier keys are down?


The old-fashioned way still works:

   #include <carbon/carbon.h>  // for GetKeys - implies need Carbon framework as well
   KeyMap theKeys;
   const bool shiftDown = theKeys[1] & kShiftKey;
   const bool ctlDown = theKeys[1] & kControlKey;
   const bool optionDown = theKeys[1] & kOptionKey;


How do I have a menu item which changes title according to the modifier keys, eg: close / close all?


Respond to the state of the modifier keys in the validateMenuItem, eg:

   #include <carbon/carbon.h>  // for GetKeys - implies need Carbon framework as well
   - (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
      SEL theAction = [menuItem action];
      if (theAction == @selector(OnFileClose:))  {
        KeyMap theKeys;
        if (theKeys[1] & kOptionKey) {
          [menuItem setTitle:@"Close all Graphs"];
        else {
          [menuItem setTitle:@"Close"];
      else if (theAction == ...
   // default - call parent
        return YESem];
      return YES;  // all the cases above are enabled unless they explicitly return


PowerPlant vs Cocoa

Cocoa minuses:

  • can't search source code to see who responds to menu events. Just because an action method is declared, doesn't mean it is connected.
  • you can't step into parent methods
  • framework source code is missing so you can't step into it to see what's happening and can't read to see what is going wrong, unlike PowerPlant.
  • using Objective-C means non-standard language and can't use standard documentation tools (eg: Doxygen) or lint etc. Even though it is based on C, the Smalltalk-like declarations and even function implementations mean no standard tools will cope. One way to get around this, and to keep code more portable, is code your business logic in standard C++ and regard objective-C as a scripting language tying a business engine to a GUI, much like the .net Forms or previous DecForms etc.

Cocoa pluses:

  • out of the box there are a lot more Cocoa examples - see /Developer/Examples
  • easier to see who will respond to menu commands in graphical sense IF they are directly connected. If they are nil-targeted or just going to FirstResponder then even more vague.

CodeWarrior vs ProjectBuilder

This is Pro9 (Pro 8 plus publicly disclosed info in the newsgroups) vs PB 2.1 (Dec 2002 dev tools)

PB lacks

  • class tree view for class browser and ability to browse without compilation
  • ability to set key bindings, especially annoying when debugging if you are used to other bindings and want to be compatible.
  • integration with other version control systems
  • doesn't return you to application thread when click Continue in debugger
  • compilation speed
  • code completion as introduced in Pro8 and often encountered on other platforms
  • class diagrams - CW Pro9 extended the Class browser and hierarchy view to cover Objective-C

PB benefits

  • direct access to GDB so can do more complex debugging including working watchpoints.
  • more flexible build process configuration, possibly command-line integration
  • more flexible compiler, eg: will warn but cope if have old ARM-style scoping of declarations in for loops (ie: expecting variable to exist outside the scope of the loop). This is useful when porting Windows code.
  • easier to work on small screen because of tabbed auto-fitting into main window, like using Visual C++. (CW for Windows has this in MDI mode but not the Mac version)
  • class browser allows you to restrict to just project classes



back to Software Engineering Ideas