我真的希望我的自定义视图与-moveLeft:
,-deleteForward:
,-selectAll:
等一起使用,但我也想传递任何我不在乎的键关于响应者链的向前发展。现在我正在覆盖-keyDown:
来呼叫[self interpretKeyEvents:[NSArray arrayWithObject:event]];
,但这似乎占据了所有关键事件,即使我的观点没有回应。
有没有办法在链中传递不需要的事件,但仍然会回复-moveLeft:
等?或者我是否需要在-keyDown:
中实施我自己的所有操作,以便我知道我做了什么并且没有回应?
答案 0 :(得分:5)
遇到这个试图找到解决同样问题的方法。从来没有在网上找到任何东西,但我想出了迄今为止似乎运作良好的东西。这就是我正在做的事情:
对您的NSTextView(或您正在使用的任何内容)进行子类化,并创建一个实例变量来临时存储按键事件。 。
@interface MyTextView : NSTextView {
NSEvent* _keyDownEvent;
}
@end
然后定义你的视图的方法(如果你使用自动引用计数,取出保留/释放垃圾):
@implementation MyTextView
- (id)initWithFrame:(NSRect)frame {
if (self = [super initWithFrame:frame]) {
_keyDownEvent = nil;
}
return self;
}
- (void)keyDown:(NSEvent*)event {
[_keyDownEvent release];
_keyDownEvent = [event retain];
[super keyDown:event];
}
- (void)doCommandBySelector:(SEL)selector {
if (_keyDownEvent && selector == @selector(noop:)) {
if ([self nextResponder]) {
[[self nextResponder] keyDown:[_keyDownEvent autorelease]];
} else {
[_keyDownEvent release];
}
_keyDownEvent = nil;
} else {
[super doCommandBySelector:selector];
}
}
- (void)dealloc {
[_keyDownEvent release];
[super dealloc];
}
@end
以下是我对此的看法。如果未按下按键,您会听到哔哔声。所以,我在NSBeep()上设置了一个断点,当程序崩溃时,我在GDB中吐出一个堆栈跟踪:
#0 0x00007fff96eb1c2d in NSBeep ()
#1 0x00007fff96e6d739 in -[NSResponder doCommandBySelector:] ()
#2 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:] ()
#3 0x00007fff96fda826 in -[NSWindow doCommandBySelector:] ()
#4 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:] ()
#5 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:] ()
#6 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:] ()
#7 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:] ()
#8 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:] ()
#9 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:] ()
#10 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:] ()
#11 0x00007fff96f486ce in -[NSTextView doCommandBySelector:] ()
#12 0x00007fff96da1c93 in -[NSKeyBindingManager(NSKeyBindingManager_MultiClients) interpretEventAsCommand:forClient:] ()
#13 0x00007fff970f5382 in -[NSTextInputContext handleEvent:] ()
#14 0x00007fff96fbfd2a in -[NSView interpretKeyEvents:] ()
#15 0x00007fff96f38a25 in -[NSTextView keyDown:] ()
#16 0x0000000100012889 in -[MyTextView keyDown:] (self=0x1004763a0, _cmd=0x7fff972b0234, event=0x100197320) at /path/MyTextView.m:24
#17 0x00007fff96a16b44 in -[NSWindow sendEvent:] ()
#18 0x00007fff969af16d in -[NSApplication sendEvent:] ()
#19 0x00007fff969451f2 in -[NSApplication run] ()
#20 0x00007fff96bc3b88 in NSApplicationMain ()
#21 0x00000001000015e2 in main (argc=3, argv=0x7fff5fbff8f0) at /path/main.m:12
发生的事情是:当按键事件不用于文本输入时,响应链上会发送“noop”命令。默认情况下,当它从响应链中掉落时会触发蜂鸣声。在我的解决方案中,NSTextView子类捕获noop命令,而是将原始keyDown事件抛出响应链。然后您的NSWindow或其他视图将正常获取任何未使用的keyDown事件。
答案 1 :(得分:3)
这是我对@daxnitro答案的迅速实施,似乎有效:
import Cocoa
class EditorTextView: NSTextView {
private var keyDownEvent: NSEvent?
required init?(coder aCoder: NSCoder) {
super.init(coder: aCoder)
}
override init() {
super.init()
}
override init(frame frameRect: NSRect, textContainer aTextContainer: NSTextContainer!) {
super.init(frame: frameRect, textContainer: aTextContainer)
}
override func keyDown(event: NSEvent) {
keyDownEvent = event
super.keyDown(event)
}
override func doCommandBySelector(aSelector: Selector) {
if aSelector != NSSelectorFromString("noop:") {
super.doCommandBySelector(aSelector)
} else if keyDownEvent != nil {
self.nextResponder?.keyDown(keyDownEvent!)
}
keyDownEvent = nil
}
}
答案 2 :(得分:0)
我在NSTextView
中有一个与自定义NSTableView
密切相关的问题。我希望能够对NSTextView
中的文本进行移位选择,但是当所有文本都被选中后,将响应者链上的shift-select传递给NSTableView
。
我的解决方案只是在responds(to:)
上覆盖NSTextView
并决定是否要在那里处理。
override func responds(to aSelector: Selector!) -> Bool
{
if aSelector == #selector(moveUpAndModifySelection(_:)) {
return selectedRange().location != 0
}
return super.responds(to: aSelector)
}