Photovor
Photovor

Reputation: 403

Programmatically create NSPopupButton and add items to list

I've been able to programmatically create a NSPopupButton and add it to my window, and I can add items to the list from the same method, but I'd like to figure out how I can add items to it from another method.

Here's what I have so far that works:

// in my .h file:
@interface AVRecorderDocument : NSDocument
{
    @private
    NSPopUpButton *button;   
}

@property (assign) IBOutlet NSWindow *mainWindow;

// in my .m file:
@implementation AVRecorderDocument
    @synthesize mainWindow;

    - (void)windowControllerDidLoadNib:(NSWindowController *) aController
    {
        NSView *superview = [mainWindow contentView];

        NSRect frame = NSMakeRect(10,10,149,22);
        NSPopUpButton *button = [[NSPopUpButton alloc]  initWithFrame:frame];

        [superview addSubview:button];
        [button release];
    }

    - (void)refreshDevices
    {
        // I'd like to add items to my popupbutton here:
        // [button addItemWithTitle: @"Item 1"];
    }

@end

Up in refreshDevices I don't get a compiler error, just nothing gets added to the popupbutton. The method refreshDevices is called from -(id)init. I've also tried putting the code that is inside the windowControllerDidLoadNib at the top of my init section, but it won't even create the popupbutton there.

Upvotes: 0

Views: 1017

Answers (1)

JDS
JDS

Reputation: 1173

There are a two problems with your code:

  1. Inside windowControllerDidLoadNib:

    You don't assign the newly created button to your ivar but only to a function local variable (with the same name as your ivar).

  2. Why nothing happens inside refreshDevices

    init is called before windowControllerDidLoadNib:, so your ivar is nil (and because of 1.). Sending messages to nil does nothing.

Solution:

  1. Remove NSPopUpButton * from windowControllerDidLoadNib: so you assign the new button to your ivar and not to some function local variable.

  2. Call refreshDevices at the end of windowControllerDidLoadNib: or at some point you know windowControllerDidLoadNib: has been called and your button is not nil.


Edit:

You should keep in mind that the moment you remove the button from the superview it is probably deallocated because you release it after creation.

The moment it is deallocated your button ivar points to an invalid/deallocated object which leads to undefined behaviour when used in this state.

I'd advise to release the button inside dealloc so you can be sure to have a valid object throughout the whole lifetime of your document object.

But nonetheless I don't know your exact use case which might require this design.

Upvotes: 2

Related Questions