2016-07-15 19 views
0

我正在嘗試編寫Mac應用程序。這樣做時,我在嘗試設置NSToolbar時遇到了一些特殊問題。以編程方式創建的NSToolbar開始爲空並且不會保存

雖然我已根據API文檔設置了所有組件,但應用程序加載時,工具欄始終爲空。當我打開自定義窗格時,工具欄項目在那裏,我可以將它們拖到工具欄中,但是當我退出應用程序並重新啓動時,更改就消失了。

注意:我知道你們許多人會認爲解決這個問題的最好方法是使用接口生成器,而不是在代碼中進行。這不是我正在尋找的答案 - 爲了更好地理解Cocoa應用程序的內部,我選擇了不使用IB的應用程序。

我已驗證(使用NSLogs)在工具欄首次初始化時,既沒有調用toolbarAllowedItemIdentifiers也沒有toolbarDefaultItemIdentifiers委託方法,但在您進入定製窗格時它們確實會被調用。

下面,請找到一個基本應用程序的最小,可驗證和完整的示例版本,演示此錯誤。任何人都可以在這個問題上了解一些情況,我將非常感謝!

感謝

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 

回答

6

添加工具欄到窗口前設置工具欄的委託。

+1

天啊!我簡直不敢相信那是這麼簡單......你不知道我花了多少小時來試圖弄清楚那裏出了什麼問題。謝謝! –

相關問題