我目前正在尝试编写一个Mac应用程序。在这样做的过程中,我在尝试设置 NSToolbar 时遇到了一些特殊的问题。
尽管我已经按照 API 文档设置了所有组件,但在加载应用程序时,工具栏始终为空。当我打开自定义窗格时,工具栏项就在那里,我可以将它们拖到工具栏中,但是当我退出应用程序并重新启动时,更改就消失了。
注意:我知道你们中的许多人会认为解决这个问题的最佳方法是使用接口构建器而不是在代码中执行此操作。这不是我正在寻找的答案 - 我选择在没有IB的情况下制作此应用程序,以便更好地了解Cocoa应用程序的内部结构。
我已经验证(使用 NSLogs)首次初始化工具栏时,既不会调用toolbarAllowedItemIdentifiers
方法,也不会调用toolbarDefaultItemIdentifiers
委托方法,但是当您进入自定义窗格时,它们确实会被调用。
下面,请找到演示此错误的基本应用程序的最小、可验证和完整的示例版本。任何能对此事有所了解的人都将不胜感激!
谢谢
定义.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
主米
#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
在将工具栏添加到窗口之前设置工具栏的委托。