强制NSPopover不成为第一个响应者与NSTokenField [英] Force NSPopover to not become first responder with NSTokenField

查看:1120
本文介绍了强制NSPopover不成为第一个响应者与NSTokenField的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个NSTokenField,我在popover中提供自定义自动完成。不幸的是,一旦popover显示,它强制NSTokenField退出第一响应者。有没有办法显示popover,但不能松开NSTokenField上的第一个响应者?

I'm having a NSTokenField and I'm providing a custom autocompletion inside the popover. Unfortunately as soon as the popover is shown it forces the NSTokenField to resign first responder. Is there a way to show the popover but not to loose the first responder on the NSTokenField?

覆盖NSTokenField的resignFirstResponder会导致NSTokenField停止工作(它不接受任何击键)。覆盖NSPopover的acceptsFirstResponder方法或设置其行为,如此< a>问题也不起作用。

Overriding NSTokenField's resignFirstResponder causes the NSTokenField to stop working (it doesn't accept any keystrokes). Overriding NSPopover's acceptsFirstResponder method or setting it's behaviour as suggested in this question does not work either.

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

The NSTokenField is not inside the NSPopover's contentViewController.view. The behaviour like the search bar in the Mailapp would be to optimal solution.

推荐答案

没有干净的方法来做到这一点。幸运的是,虽然,我做了丑陋的方式在Delicious库3 - 你需要把这个方法在NSWindow的子类,并确保文档窗口是问题是那个子类:

Unfortunately, there’s no clean way to do this. Luckily, though, I’ve done it the ugly way in Delicious Library 3—you need to put this method in a subclass of NSWindow, and make sure the document window in question is that subclass:

- (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];
}

现在确保popover的内容视图子类实现这个协议:

Now make sure the popover’s content view subclass implements this protocol:

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

请向苹果提出一个错误,要求NSPopover尊重其内容视图;它是100%的情况下,当多个开发人员编写错误,他们得到修复。

Please also file a bug with Apple to request NSPopover respect -acceptsFirstResponder of its content view; it is 100% the case that when multiple developers file bugs they get fixed.

这篇关于强制NSPopover不成为第一个响应者与NSTokenField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆