2014-01-14 2 views
4

NSTokenField가 있고 popover 내부에 사용자 지정 자동 완성 기능을 제공하고 있습니다. 불행히도 popover가 표시되는 즉시 NSTokenField는 첫 번째 응답자를 사퇴합니다. Popover를 보여줄 수있는 방법이 있긴하지만 NSTokenField의 첫 응답자를 잃어 버리지는 않습니까?NSTopenField를 사용하여 NSPopover가 첫 번째 응답자가되지 않도록하십시오.

NSTokenField의 resignFirstResponder를 무시하면 NSTokenField가 작동을 멈추고 (키 입력이 허용되지 않음) 발생합니다. NSPopover의 acceptsFirstResponder 메서드를 재정의하거나 this 질문에 제안 된대로 동작을 설정하는 것은 작동하지 않습니다.

편집 : NSTokenField는 NSPopover의 contentViewController.view 안에 없습니다. Edit2 : Mailapp의 검색 창과 같은 동작은 최적의 솔루션입니다. Mailapp

Popover

+0

아마도 'NSPopover'에로드 된 '보기'는 NIB 파일에서 구성되고보기 컨트롤러를 통해로드됩니까? 해당 NIB 파일에 * 첫 번째 응답자가 올바르게 설정되어 있습니까? AFAIK, Popover는 Windows 및 View의 일반적인 응답 * 동작을 존중해야합니다. – trojanfoe

+0

@tojanfoe 질문이 잘못 이해 될 수있어서 유감입니다. NSTokenField는 popover 안에 없습니다. 질문을 편집하고 명확성을 위해 이미지를 추가했습니다. – Lukas

+1

"NSPopover"이외의 것을 사용해야 할 수도 있습니다. popover의 예상되는 동작은 사용자가 상호 작용할 수있는 몇 가지 컨트롤을 제공하는 것입니다. – trojanfoe

답변

6

불행하게도,이 작업을 수행 할 청소 방법이 없다. 이제

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

합니다 다행히,하지만 나는 그것을 맛있는 라이브러리의 추악한 방법으로 수행 한 3 - 당신은 NSWindow 표시의 하위 클래스에서이 메서드를 넣어 만들 필요가 있는지 문제가되는 문서 창은 서브 클래스 확인 팝 오버의 내용보기 서브 클래스는이 프로토콜을 구현합니다

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

또한 NSPopover이 컨텐츠보기의 -acceptsFirstResponder을 존중 요청 애플과 버그를 제출하시기 바랍니다; 여러 개발자가 버그를 신고 할 때 100 % 수정됩니다.

+0

당신은 생명의 은인입니다. 나는 당신의 앱을 살펴 봤는데 멋지게 보였다. 정확히 내가 재현하려는 것. iOS 놀이터에서 오면 OS X을 사용하기가 어렵다.) – Lukas

+1

OS X은 몇 년 동안 추한 발걸음을 내디뎠다. 실제로 보여주기 시작했다.그러나 나는 아직도 그것을 좋아한다. –

+0

이 위대한 답변 주셔서 감사합니다, 그것은 많이 도움이됩니다! – sebastien

0

팝업 내용 (텍스트보기?)의 하위 클래스를 만들고 -(void)canBecomeKeyView을 구현하십시오. 거기에 아무 것도 돌려 보내지 마라. 이는 popover가 표시 될 때 한 번만 호출되므로 계속 상호 작용할 수 있지만 더 이상 첫 번째 응답자 상태를 훔치지는 않습니다.

+0

이것은 작동하지 않습니다. NSPopover에서 NSTextField로 시도했지만 popover는 여전히 첫 번째 응답자를 훔칩니다. – GenericPtr

관련 문제