2014-01-14 59 views
4

我有一個NSTokenField,我在popover中提供了一個自定義的自動完成。不幸的是,一旦顯示彈出窗口,它就會迫使NSTokenField退出第一響應者。有沒有辦法顯示彈出窗口,但不能鬆開NSTokenField上的第一響應者?強制NSPopover不成爲NSTokenField的第一響應者

覆蓋NSTokenField的resignFirstResponder會導致NSTokenField停止工作(它不接受任何按鍵操作)。如this問題所示,重寫NSPopover的accepFirstResponder方法或設置它的行爲也不起作用。

編輯:NSTokenField不在NSPopover的contentViewController.view中。編輯2:像Mailapp中的搜索欄那樣的行爲將是最佳解決方案。 Mailapp

Popover

+0

據推測,加載到「NSPopover」中的「視圖」是從NIB文件配置並通過視圖控制器加載的?該NIB文件中的* first responder *設置是否正確? AFAIK,popover應該遵守窗口和視圖的通常的* first responder *行爲。 – trojanfoe

+0

@tojanfoe對不起,這個問題可能被誤解了。 NSTokenField不在popover內。爲了清晰起見,我編輯了該問題並添加了一張圖片。 – Lukas

+1

也許你需要使用「NSPopover」以外的東西。 popover的預期行爲是提供一些用戶可以與之交互的控件。 – trojanfoe

回答

6

不幸的是,有沒有乾淨的方式來做到這一點。幸運的是,雖然,我已經做到了美味的圖書館醜陋的方式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 

也請把與蘋果的錯誤,請求NSPopover尊重其內容視圖的-acceptsFirstResponder;當多個開發者提交bug修復時,這是100%的情況。

+0

你是救生員。我看了一下你的應用程序,它看起來很棒。正是我想要重現的。當你來自iOS遊樂場時,很難與OS X一起工作;) – Lukas

+1

OS X已經是幾年來醜陋的一步,它真的開始顯現。但我仍然喜歡它。 –

+0

感謝這個偉大的答案,它幫助了我很多! – sebastien

0

製作您的彈出式內容(文本視圖?)的子類並執行-(void)canBecomeKeyView。返回沒有。當彈出窗口被顯示時它只被調用一次,所以你仍然可以與它交互,但它不再竊取第一個響應者狀態。

+0

這不起作用。試用NSPopover中的NSTextField,popover仍然搶先搶救。 – GenericPtr

相關問題