NSToolbar created programmatically starts empty and won't save

∥☆過路亽.° 提交于 2020-12-06 04:45:29

问题


I'm currently trying to write a Mac application. In doing so, I'm having some peculiar problems when trying to setup an NSToolbar.

Although I have setup all the components as per the API documentation, when the application loads, the toolbar always starts empty. When I open the customisation pane, the toolbar items are there, and I can drag them into the toolbar, but when I quit the application and restart the changes are gone.

Note: I am aware that many of you will be of the opinion that the best way to solve this is to use interface builder rather than doing it in code. That is not the answer I am looking for - I chose to make this application without IB in order to better understand the internals of a Cocoa app.

I have verified (with NSLogs) that neither the toolbarAllowedItemIdentifiers nor the toolbarDefaultItemIdentifiers delegate methods get called when the toolbar is first initialised, but they do get called when you enter the customisation pane.

Below, please find a minimal, verifiable and complete example version of a basic app that demonstrates this bug. Anyone that can shed some light on this matter would be hugely appreciated!

Thanks

Defines.h

#define UNUSED(x) (void)(x)
#define TOOLBAR_ONE @"ONE"
#define TOOLBAR_TWO @"TWO"
#define TOOLBAR_IDENT @"TOOLBAR"

#define WINDOW_MASK NSTitledWindowMask | \
   NSClosableWindowMask | \
   NSResizableWindowMask | \
   NSMiniaturizableWindowMask

main.m

#import "BWAppDelegate.h"
#import <AppKit/AppKit.h>

int main(void) {
   @autoreleasepool {
      NSApplication* application = [NSApplication sharedApplication];
      BWAppDelegate* delegate    = [[BWAppDelegate alloc] init];

      application.delegate = delegate;
      [application run];

      return EXIT_SUCCESS;
   }
}

BWAppDelegate.h

#import <Cocoa/Cocoa.h>

#import "BWMainToolbarDelegate.h"

@interface BWAppDelegate : NSObject<NSApplicationDelegate>

@property (atomic, strong) NSWindow*              window;
@property (atomic, strong) BWMainToolbarDelegate* toolbarDelegate;

@end

BWAppDelegate.m

#import <AVFoundation/AVFoundation.h>
#import <AppKit/AppKit.h>
#import <Cocoa/Cocoa.h>

#import "BWAppDelegate.h"
#import "Defines.h"

@implementation BWAppDelegate

@synthesize window, toolbarDelegate;

- (void) applicationDidFinishLaunching: (NSNotification*) aNotification
{
   UNUSED(aNotification);
   NSRect dims = NSMakeRect(0, 0, 300, 300);

   self.window = [[NSWindow alloc] initWithContentRect:dims
                                             styleMask:WINDOW_MASK
                                               backing:NSBackingStoreBuffered
                                                 defer:NO];
   [self.window makeKeyAndOrderFront:nil];
   self.window.toolbar = [[NSToolbar alloc] initWithIdentifier:TOOLBAR_IDENT];
   toolbarDelegate     = [[BWMainToolbarDelegate alloc] initWithToolbar:self.window.toolbar];
}

@end

BWMainToolbarDelegate.h

#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>

@interface BWMainToolbarDelegate : NSObject<NSToolbarDelegate>

- (instancetype) initWithToolbar: (NSToolbar*) theToolbar;

- (NSArray*) toolbarAllowedItemIdentifiers: (NSToolbar*) toolbar;
- (NSArray*) toolbarDefaultItemIdentifiers: (NSToolbar*) toolbar;
- (NSToolbarItem*)   toolbar: (NSToolbar*) toolbar
       itemForItemIdentifier: (NSString*) identifier
   willBeInsertedIntoToolbar: (BOOL) flag;

@end

BWMainToolbarDelegate.m

#import "BWMainToolbarDelegate.h"
#import "Defines.h"

@implementation BWMainToolbarDelegate {
   NSToolbar* toolbar;
}

- (instancetype) initWithToolbar: (NSToolbar*) theToolbar
{
   self = [super init];
   if(self) {
      toolbar = theToolbar;
      toolbar.displayMode = NSToolbarDisplayModeIconAndLabel;
      toolbar.allowsUserCustomization = YES;
      toolbar.autosavesConfiguration = YES;
      toolbar.delegate    = self;
   }
   return self;
}

- (NSArray*) toolbarAllowedItemIdentifiers: (NSToolbar*) theToolbar
{
   UNUSED(theToolbar);
   return @[TOOLBAR_ONE, TOOLBAR_TWO];
}

- (NSArray*) toolbarDefaultItemIdentifiers: (NSToolbar*) theToolbar
{
   UNUSED(theToolbar);
   return @[TOOLBAR_ONE, TOOLBAR_TWO];
}

- (NSToolbarItem*)   toolbar: (NSToolbar*) theToolbar
       itemForItemIdentifier: (NSString*) identifier
   willBeInsertedIntoToolbar: (BOOL) flag
{
   UNUSED(flag);
   NSToolbarItem* returnVal = nil;
   NSString*      label;

   if([theToolbar.identifier isEqualToString:TOOLBAR_IDENT]) {

      if([identifier isEqualToString:TOOLBAR_ONE]) {
         returnVal = [[NSToolbarItem alloc] initWithItemIdentifier:TOOLBAR_ONE];
         label     = @"Toolbar One";
      } else if([identifier isEqualToString:TOOLBAR_TWO]) {
         returnVal = [[NSToolbarItem alloc] initWithItemIdentifier:TOOLBAR_TWO];
         label     = @"Toolbar TWO";
      }
   }

   returnVal.label        = label;
   returnVal.paletteLabel = label;
   return returnVal;
}

@end

回答1:


Set the delegate of the toolbar before adding the toolbar to the window.



来源:https://stackoverflow.com/questions/38391875/nstoolbar-created-programmatically-starts-empty-and-wont-save

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!