以编程方式创建的NSToolbar为空,不会保存

时间:2016-07-15 08:52:29

标签: objective-c macos cocoa nstoolbar

我目前正在尝试编写Mac应用程序。在这样做时,我在尝试设置NSToolbar时遇到了一些特殊问题。

虽然我已根据API文档设置了所有组件,但在加载应用程序时,工具栏始终为空。当我打开自定义窗格时,工具栏项目就在那里,我可以将它们拖到工具栏中,但是当我退出应用程序并重新启动时,更改就不见了。

注意:我知道很多人会认为解决这个问题的最佳方法是使用接口构建器而不是在代码中使用它。这不是我要找的答案 - 我选择在没有IB的情况下制作这个应用程序,以便更好地理解Cocoa应用程序的内部。

我已经验证(使用NSLogs),首次初始化工具栏时,toolbarAllowedItemIdentifierstoolbarDefaultItemIdentifiers委托方法都不会被调用,但是当您进入自定义窗格时,它们会被调用。

下面,请找一个演示此错误的基本应用的最小,可验证且完整的示例版本。任何能够解释这个问题的人都会非常感激!

由于

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 个答案:

答案 0 :(得分:6)

在将工具栏添加到窗口之前设置工具栏的委托。