我有一个NSTokenField,并且在弹出框内提供了一个自定义自动补全功能。不幸的是,一旦显示弹出窗口,它就会强制NSTokenField退出第一响应者。有没有一种方法可以显示弹出窗口,但又不会丢失NSTokenField上的第一个响应者?

重写NSTokenField的resignFirstResponder会导致NSTokenField停止工作(它不接受任何击键)。覆盖NSPopover的acceptsFirstResponder方法或按照this问题中的建议设置其行为也不起作用。

编辑:NSTokenField不在NSPopover的contentViewController.view中。
Edit2:Mailapp中搜索栏之类的行为将是最佳解决方案。

最佳答案

不幸的是,没有干净的方法可以做到这一点。幸运的是,尽管我在Delicious Delicious Library 3中做到了这一丑陋的方式-您需要将此方法放在NSWindow的子类中,并确保所讨论的文档窗口是该子类:

- (BOOL)makeFirstResponder:(NSResponder *)responder;
{
    // Prevent popover content view from forcing our current first responder to resign
    if (responder != self.firstResponder && [responder isKindOfClass:[NSView class]]) {
        NSWindow *const newFirstResponderWindow = ((NSView *)responder).window;
        NSWindow *currentFirstResponderWindow;

        NSResponder *const currentFirstResponder = self.firstResponder;
        if ([currentFirstResponder isKindOfClass:[NSWindow class]])
            currentFirstResponderWindow = (id)currentFirstResponder;
        else if ([currentFirstResponder isKindOfClass:[NSView class]])
            currentFirstResponderWindow = ((NSView *)currentFirstResponder).window;

        // Prevent some view in popover from stealing our first responder, but allow the user to explicitly activate it with a click on the popover.
        // Note that the current first responder may be in a child window, if it's a control in the "thick titlebar" area and we're currently full-screen.
        if (newFirstResponderWindow != self && newFirstResponderWindow != currentFirstResponderWindow && self.currentEvent.window != newFirstResponderWindow)
            for (NSView *responderView = (id)responder; responderView; responderView = responderView.superview)
                if ([responderView conformsToProtocol:@protocol(LIPopoverFirstResponderStealingSuppression)] &&
                    ((id <LIPopoverFirstResponderStealingSuppression>)responderView).suppressFirstResponderWhenPopoverShows)
                    return NO;
    }

    return [super makeFirstResponder:responder];
}


现在,确保弹出式窗口的内容视图子类实现了以下协议:

// NSPopover doesn't respect -acceptsFirstResponder of its content view (Radar 10666891).
@protocol LIPopoverFirstResponderStealingSuppression <NSObject>
@property (readonly, nonatomic) BOOL suppressFirstResponderWhenPopoverShows;
@end


还请向Apple提交错误,以请求NSPopover尊重其内容视图的-acceptsFirstResponder;当多个开发人员提交错误时,他们得到修复的情况是100%。

关于macos - 强制NSPopover不再通过NSTokenField成为第一响应者,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21110622/

10-13 02:26