NSAlert:将第二个按钮设置为默认按钮和“取消”按钮

时间:2018-11-17 16:37:28

标签: macos cocoa nsalert

Apple最初的HIG(不幸的是现在从网站上消失了)说:

对话框中最右边的按钮(动作按钮)是用于确认警报消息文本的按钮。动作按钮通常是但并非总是默认按钮

就我而言,我有一些破坏性操作(例如擦除磁盘),需要“安全”确认对话框,如下所示:

"Safe" confirmation dialog

最糟糕的选择是创建一个对话框,其中最右边的按钮将变为“不擦除”按钮,而其左边的一个按钮(通常为“取消”按钮)将成为“擦除”按钮,因为这很容易导致灾难(一次happened to me使用Microsoft制作的对话框),因为人们受过训练,只要他们想取消操作就可以单击第二个按钮。

因此,我需要的是,左(取消)按钮既成为默认按钮,又对Return,Esc和cmd-period键做出反应。

要将其设置为默认值并对Return键做出反应,我只需将第一个按钮的keyEquivalent设置为空字符串,第二个按钮的设置为“ \ r”。

但是当Esc或cmd-时,如何使警报也取消。输入?

1 个答案:

答案 0 :(得分:1)

以通常的方式设置NSAlert,并指定默认按钮。创建一个具有空边界的NSView新子类,并将其添加为NSAlert的附件视图。在子类的performKeyEquivalent中,检查Esc以及它是否与调用[-NSApplication stopModalWithCode:][-NSWindow endSheet:returnCode:]相匹配。

#import "AppDelegate.h"

@interface AlertEscHandler : NSView
@end

@implementation AlertEscHandler
-(BOOL)performKeyEquivalent:(NSEvent *)event {
    NSString *typed = event.charactersIgnoringModifiers;
    NSEventModifierFlags mods = (event.modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask);
    BOOL isCmdDown = (mods & NSEventModifierFlagCommand) != 0;
    if ((mods == 0 && event.keyCode == 53) || (isCmdDown && [typed isEqualToString:@"."])) { // ESC key or cmd-.
        [NSApp stopModalWithCode:1001]; // 1001 is the second button's response code
    }
    return [super performKeyEquivalent:event];
}
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [self alertTest];
    [NSApp terminate:0];
}

- (void)alertTest {
    NSAlert *alert = [NSAlert new];
    alert.messageText = @"alert msg";
    [alert addButtonWithTitle:@"OK"];
    NSButton *cancelButton = [alert addButtonWithTitle:@"Cancel"];
    alert.window.defaultButtonCell = cancelButton.cell;
    alert.accessoryView = [AlertEscHandler new];
    NSModalResponse choice = [alert runModal];
    NSLog (@"User chose button %d", (int)choice);
}