Search code examples
objective-cmacoscocoansmenuitemnsviewcontroller

NSMenuItem with custom view does not update


I have a NSMenuItem with a custom view. However, when I want to update the first row in the menu it add the content as it is in the xib file, not as I set it.

My code: AppDelegate.m:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    _helper = [[Helper alloc] init];

    statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
    [statusItem setMenu:self.statusMenu];
    [statusItem setTitle:@"GravAccount"];
    [statusItem setHighlightMode:YES];

    _gravatarLoader = [[GravatarLoader alloc] initWithTarget:self andHandle:@selector(setGravatarImage:)];

    // Get email address
    _email = [_helper getEmailAddress];

    if (_email != nil)
    {
        [_gravatarLoader loadEmail:_email withSize:50.0];
    }
}

- (void)setGravatarImage:(NSImage*)image
{
    NSLog(@"Image loaded!");

    GravatarMenuItem *menuItem = [[GravatarMenuItem alloc] initWithNibName:@"GravatarMenuItem" bundle:nil];
    [menuItem.label setTitle:_email];
    [menuItem.imageView setImage:image];

    NSLog(@"Email: %@", _email);

    NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
    [item setView:menuItem.view];

    [self.statusMenu removeItemAtIndex:0];
    [self.statusMenu insertItem:item atIndex:0];
}

GravatarMenuItem.h:

#import <Cocoa/Cocoa.h>

@interface GravatarMenuItem : NSViewController

@property (nonatomic, strong) IBOutlet NSImageView *imageView;
@property (nonatomic, strong) IBOutlet NSTextFieldCell *label;

@end

The outlets are linked in the XIB file on the file's owner.

This is the result: Log:

2012-03-09 16:57:24.314 appName[51158:403] Image loaded!
2012-03-09 16:57:24.316 appName[51158:403] Email: Paul@******.se

Result:
Result


Solution

  • When you do:

    GravatarMenuItem *menuItem = [[GravatarMenuItem alloc] initWithNibName:@"GravatarMenuItem" bundle:nil];
    

    It only creates the view controller. It doesn't actually load the view from the nib. When you access the properties, they are most likely nil as the view has not been loaded (and the connections have not been made).

    If you update your code to the following, everything should work fine:

    GravatarMenuItem *menuItem = [[GravatarMenuItem alloc] initWithNibName:@"GravatarMenuItem" bundle:nil];
    [menuItem view]; // load the view from the nib
    [menuItem.label setTitle:_email];
    [menuItem.imageView setImage:image];