以编程方式创建的 NSToolbar 开始时为空并且不会保存
NSToolbar created programmatically starts empty and won't save
我目前正在尝试编写 Mac 应用程序。这样做时,我在尝试设置 NSToolbar 时遇到了一些特殊问题。
虽然我已经按照 API 文档设置了所有组件,但是当应用程序加载时,工具栏始终是空的。当我打开自定义窗格时,工具栏项目在那里,我可以将它们拖到工具栏中,但是当我退出应用程序并重新启动时,更改就消失了。
注意:我知道你们中的许多人会认为解决此问题的最佳方法是使用界面生成器而不是在代码中进行。这不是我正在寻找的答案 - 我选择在没有 IB 的情况下制作这个应用程序,以便更好地理解 Cocoa 应用程序的内部结构。
我已经(使用 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
在将工具栏添加到 window 之前设置工具栏的委托。
我目前正在尝试编写 Mac 应用程序。这样做时,我在尝试设置 NSToolbar 时遇到了一些特殊问题。
虽然我已经按照 API 文档设置了所有组件,但是当应用程序加载时,工具栏始终是空的。当我打开自定义窗格时,工具栏项目在那里,我可以将它们拖到工具栏中,但是当我退出应用程序并重新启动时,更改就消失了。
注意:我知道你们中的许多人会认为解决此问题的最佳方法是使用界面生成器而不是在代码中进行。这不是我正在寻找的答案 - 我选择在没有 IB 的情况下制作这个应用程序,以便更好地理解 Cocoa 应用程序的内部结构。
我已经(使用 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
在将工具栏添加到 window 之前设置工具栏的委托。