本文章介绍主要介绍 NSTextField对键盘事件的响应,比如复制、粘贴、全选、拷贝等。
分类方式实现
NSTextField+KBCopy.h文件
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSTextField (KBCopy)
@end
NS_ASSUME_NONNULL_END
NSTextField+KBCopy.m文件
#import "NSTextField+KBCopy.h"
@implementation NSTextField (KBCopy)
//此处与网易有道词典冲突,修复
- (BOOL)performKeyEquivalent:(NSEvent *)event
{
if (([event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == NSEventModifierFlagCommand) {
// The command key is the ONLY modifier key being pressed.
if ([[event charactersIgnoringModifiers] isEqualToString:@"x"]) {
return [NSApp sendAction:@selector(cut:) to:[[self window] firstResponder] from:self];
} else if ([[event charactersIgnoringModifiers] isEqualToString:@"c"]) {
return [NSApp sendAction:@selector(copy:) to:[[self window] firstResponder] from:self];
} else if ([[event charactersIgnoringModifiers] isEqualToString:@"v"]) {
return [NSApp sendAction:@selector(paste:) to:[[self window] firstResponder] from:self];
} else if ([[event charactersIgnoringModifiers] isEqualToString:@"a"]) {
return [NSApp sendAction:@selector(selectAll:) to:[[self window] firstResponder] from:self];
}
}
return [super performKeyEquivalent:event];
}
@end
直到我忽然间发现一个 bug:与网易有道词典的划线查单词
功能冲突,然后发现冲突的是Command+C
等快捷键。
后来我看到一篇文章说:performKeyEquivalent
重写是苹果不推荐这样做的。
新的实现方式
首先,让我们看看 NSTextField的继承方式:
NSSTextField 继承自 NSControl,NSControl继承自 NSView。NSView 中有performKeyEquivalent方法。
performKeyEquivalent即为我们苦苦寻找的那个"她"
import Cocoa
class KeyEventTextField: NSTextField {
private let commandKey = NSEvent.ModifierFlags.command.rawValue
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
}
override func performKeyEquivalent(with event: NSEvent) -> Bool {
if (event.modifierFlags.rawValue & event.modifierFlags.intersection(.deviceIndependentFlagsMask).rawValue == commandKey){
switch event.charactersIgnoringModifiers! {
case "x":
NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self)
case "c":
NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self)
case "v":
NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self)
case "z":
NSApp.sendAction(Selector(("undo:")), to:nil, from:self)
case "a":
NSApp.sendAction(#selector(NSStandardKeyBindingResponding.selectAll(_:)), to:nil, from:self)
default:
break
}
}
return true
}
}
如上代码,我们写了一个NSTextField 的子类,重写performKeyEquivalent
方法,用于处理键盘事件。
接下来,我们一起解读下这段简单的代码:
- 首先我们来看判断条件,大致的意思是判断我们有没有按辅助键,辅助键是否是
command
- 接下来判断我们按的字母键是哪个,并执行对应的操作。
用法就超级简单的,只实例化我们的子类(本例为KeyEventTextField
)即可。
如果是在 XIB中,则修改 class 即可:

总结:
- 键盘事件是 NSView 的performKeyEquivalent方法中处理的,所以不仅仅是 NSTextField,NSButton 等继承自 NSView 的类皆可使用此方法处理键盘快捷键。
- 不建议用分类实现,可能有未知 bug。
网友评论