모달 ViewController 프리젠 테이션 스타일이 UIModalPresentationFormSheet 인 경우 iPad 키보드가 닫히지 않습니다.


214

노트 :

iOS 4.3부터 해결책에 대해 허용 된 답변 (최고 투표 대상 아님)을 참조하십시오.

질문 은 iPad 키보드에서 발견 된 동작에 관한 것으로, 내비게이션 컨트롤러와 함께 모달 대화 상자에 표시되면 해제되지 않습니다.

기본적으로 탐색 컨트롤러에 다음과 같은 줄을 표시하면 다음과 같습니다.

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

키보드가 닫히기를 거부합니다. 이 줄을 주석 처리하면 키보드가 사라집니다.

...

두 개의 textFields, username과 password가 있습니다. username에는 Next 버튼이 있고 password에는 Done 버튼이 있습니다. 모달 탐색 컨트롤러에 이것을 제시하면 키보드가 사라지지 않습니다.

공장

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
[self.view addSubview:b.view];

작동하지 않습니다

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
UINavigationController *navigationController = 
[[UINavigationController alloc]
 initWithRootViewController:b];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
navigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[b release];

탐색 컨트롤러 부분을 제거하고 'b'를 모달보기 컨트롤러로 표시하면 작동합니다. 네비게이션 컨트롤러에 문제가 있습니까?

공장

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
b.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:b animated:YES];
[b release];

공장

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
UINavigationController *navigationController = 
    [[UINavigationController alloc]
         initWithRootViewController:b];
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[b release];

다음 SO 질문에 같은 문제가있는 것 같지만 답변이 없습니다 : stackoverflow.com/questions/3019709/…
Kalle

+1 훌륭한 설명 감사합니다. 그러나 그 방법을 어디에 넣어야합니까? 모델 컨트롤러를 제시하기위한 코드를 작성하는 곳에서는 작동하지 않는 것 같습니다 ...
Lorenzo B

1
모달 뷰 컨트롤러 클래스 자체에 있어야합니다.
Kalle

감사. 내가 참조. UINavigationController수업 카테고리에 넣는 것을 해결했습니다 . 건배.
Lorenzo B

나는이 질문에 대해 너에게 빚을졌다. resignFirstResponder실행 중이지만 키보드가 여전히 표시되는 것에 놀랐습니다 . 내 시나리오 (navig contrllr가있는 presentationFormSheet)는 귀하와 정확히 동일합니다. 정말 감사합니다!!
sErVerdevIL

답변:


115

모달로 표시되는 뷰 컨트롤러에서 재정 의하여 다음 disablesAutomaticKeyboardDismissal을 반환하십시오 NO.

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

그렇다. 4.3 이후 이것은 사실이다. 질문을 업데이트합니다. 감사!
Kalle

2
이 요구는 네비게이션 컨트롤러에 추가 할
pottedmeat

1
예, NavigationController에서 덮어 쓸 때 작동합니다. 그것이 실제로 나를 위해 일한 유일한 것입니다.
James Laurenstin

생명의 은인! 애플은 왜 이런 일을합니까? 분명히 기본값은 NO로 설정해야하며 실제로 원할 경우 변경할 수 있습니다.
SomaMan

UIViewController 파생 클래스에서 작동하지 않으므로 disablesAutomaticKeyboardDismissal이 호출되지 않습니다.
Jorge Arimany

172

이것은 Apple 엔지니어에 의해 "의도 한대로 작동"으로 분류되었습니다. 나는 이것을 위해 잠시 동안 버그를 제기했다. 그들의 추론은 사용자가 종종 모달 형식으로 데이터를 입력하기 때문에 "도움이되고"모달보기 내에서 일반적으로 다양한 전환으로 인해 키보드가 반복적으로 표시되거나 숨겨 질 수있는 경우 키보드를 계속 보이게합니다.

편집 : 개발자 포럼에서 Apple 엔지니어 의 답변 은 다음과 같습니다.

UIModalPresentationFormSheet 스타일이 표시 되었습니까? 잦은 인 / 아웃 애니메이션을 피하기 위해 첫 번째 응답자가없는 경우에도 키보드가 화면에 표시되는 경우가 있습니다. 이것은 버그가 아닙니다.

이것은 많은 사람들에게 문제를 안겨주지만 (현재 포함되어 있음) 현재 해결 방법이없는 것 같습니다.

최신 정보:

iOS 4.3 이상에서는 뷰 컨트롤러에서`-disablesAutomaticKeyboardDismissal '을 구현하여 NO를 반환 할 수 있습니다.

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

문제가 해결되었습니다.


7
일시 정지 좋아, 와우. 고마워요. 젠장 애플 .. :(
Kalle

Apple에 버그 보고서를 제출 했습니까? ID # 8384423에 따라 그렇게했습니다. 또한 행동을 재현하기 위해 샘플 신청서를 제출했습니다.
얽히고 설킨 개구리

3
iOS 4.3부터는이 문제를 해결하는 disablesAutomaticKeyboardDismissal 메소드가 있습니다.
Kalle

5
나는 자동 KeyboardDismissal 메소드를 비활성화하려고 시도하지만 여전히 문제를 해결하지 못했습니다. 어떻게 해결합니까?
R. Dewi

3
@Snips : 모달 폼 시트를 제시 할 때이를 네비게이션 컨트롤러로 반환 하고 사용하려면 UINavigationController재정의 하는 서브 클래스 를 만들어야합니다 . 아래 @ miha-hribar의 답변을 참조하십시오. disablesAutomaticKeyboardDismissalNO
Pascal

149

로 모달을 표시하는 경우주의하십시오 UINavigationController. 그런 다음 disablesAutomaticKeyboardDismissal뷰 컨트롤러가 아닌 내비게이션 컨트롤러에서을 설정해야합니다 . 카테고리를 사용하여 쉽게 수행 할 수 있습니다.

파일 : UINavigationController + KeyboardDismiss.h

#import <Foundation/Foundation.h>

@interface UINavigationController (KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal;

@end

파일 : UINavigationController + KeyboardDismiss.m

#import "UINavigationController+KeyboardDismiss.h"

@implementation UINavigationController(KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}

@end

UINavigationController를 사용하는 파일에서 카테고리를 가져 오는 것을 잊지 마십시오.


19
하나는, 마지막으로 내가 강조이 문제에 대한 정보의 누락 된 부분을 참조하십시오 일 개 필요는 무시할 수 있음을 disablesAutomaticKeyboardDismissalUINavigationController이 문제를 해결하기 위해이 아닌 자신의 뷰 컨트롤러.
DarkDust

좋은! 내가 필요한 것만 감사합니다.
저스틴

완전한. 공식 문서에서는 명확하지 않지만 UINavigationController가 응답자 체인에 있기 때문에 의미가 있습니다. 훌륭한 답변입니다. 감사합니다!
imnk

1
UISplitViewController에서 모달 대화 상자를 제시하고 있습니다. 위의 코드를 시도했지만 UINavigationController 대신 UISplitViewController를 대체했지만 여전히 작동하지 않습니다. 이 메소드가 UISplitViewController에서도 작동해야합니까?
Snips

6
카테고리에서 중복 메소드를 구현하는 것은 좋지 않습니다. 어떤 구현이 호출 될지 확신 할 수 없으므로 일관성이없는 동작을 기대할 수 있습니다. UINavigationController에서 상속하고 사용자 정의 클래스의 메소드를 대체하는 것이 좋습니다.
sean woodward

51

UIModalPresentationPageSheet프레젠테이션 스타일 을 사용하고 프리젠 테이션 직후 크기를 조정 하여이 문제를 해결 했습니다. 이렇게 :

viewController.modalPresentationStyle = UIModalPresentationPageSheet;
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:viewController animated:YES];
viewController.view.superview.autoresizingMask = 
    UIViewAutoresizingFlexibleTopMargin | 
    UIViewAutoresizingFlexibleBottomMargin;    
viewController.view.superview.frame = CGRectMake(
    viewController.view.superview.frame.origin.x,
    viewController.view.superview.frame.origin.y,
    540.0f,
    529.0f
);
viewController.view.superview.center = self.view.center;
[viewController release];

흠 ... 이것은 옳지 않습니다 ... 크기를 조정하면 모달이 웃겨집니다. 새로운 크기 상자 또는 무언가에 맞게 내용을 찌그러 뜨리는 것 같습니다 ... 모든 것이 재미있게 보입니다. :(
toofah

이 모달가있는 동안은 전체 페이지 뷰 인 것처럼 성장 / 축소됩니다 회전 경우이 하나 회전 문제는 ...도있다
toofah

2
toofah, 회전 할 때 수축 / 성장 문제를 처리하기 위해 코드를 편집했습니다. Superview에 유연한 상단 및 하단 마진을 제공하는 문제입니다. 다른 동작을보고 있는지 잘 모르겠습니다.
azdev

1
이것은 다른 뷰를이 뷰 위에 올리지 않는 한 작동합니다. UIModalPresentationPageSheet 제시보기 위로 푸시 된보기를 닫으면 원래 크기로 돌아갑니다.
V1ru8

효과가있었습니다. 그러나보기의 단어가 약간 흐리게 보입니다. 이유를 모르겠습니다.
jeswang

1

다른 모달 디스플레이를 토글하면 키보드가 사라질 수 있습니다. 예쁘지 않고 애니메이션되지는 않지만 멀리 갈 수 있습니다.

수정 사항이 있으면 좋을 것이지만 지금은 작동합니다. 카테고리에 쐐기를 UIViewController넣고 키보드를 놓을 때 호출 할 수 있습니다.

@interface _TempUIVC : UIViewController
@end

@implementation _TempUIVC
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}
@end

@implementation UIViewController (Helpers)

- (void)_dismissModalViewController {
    [self dismissModalViewControllerAnimated:NO];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
    [self release];
}

- (void)forceKeyboardDismissUsingModalToggle:(BOOL)animated {
    [self retain];
    _TempUIVC *tuivc = [[_TempUIVC alloc] init];
    tuivc.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentModalViewController:tuivc animated:animated];
    if (animated) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_dismissModalViewController) name:UIKeyboardDidHideNotification object:nil];
    } else
        [self _dismissModalViewController];
    [tuivc release];
}

@end

viewDidAppear / viewDidDisappear를 볼 때 모든주의 사항이 호출 될 때주의하십시오. 내가 말했듯이, 그것은 예쁘지 않지만 작동합니다.

-아담


1

당신은 또한 관용구를 확인하여 보편적 인 응용 프로그램 에서이 문제를 해결할 수 있으며 iPad 인 경우 키보드를 전혀 자동으로 팝업하지 않고 사용자가 편집하려는 것을 탭하도록하십시오.

가장 좋은 해결책은 아니지만 매우 간단하며 다음 주요 iOS 릴리스에서 중단 될 멋진 해킹이 필요하지 않습니다. :)


1

이 코드를 viewWillDisappear에 넣으십시오 : 현재 컨트롤러의 메소드는 이것을 수정하는 또 다른 방법입니다.

Class UIKeyboardImpl = NSClassFromString(@"UIKeyboardImpl");
id activeInstance = [UIKeyboardImpl performSelector:@selector(activeInstance)];
[activeInstance performSelector:@selector(dismissKeyboard)];

1

모달 대화 상자에서 함수 disablesAutomaticKeyboardDismissal추가가 disablesAutomaticKeyboardDismissal작동하지 않는다는 것을 알았습니다 UITextField.

온 스크린 키보드는 사라지지 않을 것입니다.

내 솔루션은 대화 상자에서 모든 텍스트 입력 컨트롤 을 비활성화 한 다음 잠시 후 관련 컨트롤을 다시 활성화하는 것이 었습니다.

아이폰 OS는 그 어느 것도 볼 때처럼 보인다 UITextField컨트롤을 사용할 수 없습니다, 그때는 않습니다 키보드 제거하기.


0

나는 이것을 보았지만 컨트롤러 클래스가 UITextField 대리자로 올바르게 연결되어 있다고 확신합니까?


수동으로 설정하면 대리자 메서드가 호출됩니다.
Kalle

0

어쩌면 YES하지만, NO를 반환하지 않습니다. 그래서 멀리 갈 수 있습니다.

그리고 당신도 textFieldShouldEndEditing예를 반환합니까?

그리고 당신은 발사 [nextResponder becomeFirstResponder]?! 미안 내가 지금 참조

또한 "편집 가능한"속성이 모두 FALSE로 설정된 많은 UITextView가 있습니다.

우연히 그 tag값이 secondField.tag+1? 그렇다면 첫 번째 응답자를 사직하는 대신 첫 번째 응답자가되도록 지시하는 것입니다. 어쩌면 NSLog ()를 if 구조에 넣을 수도 있습니다.


1
아니요 = 내가 말할 수있는 줄 바꿈을 삽입하지 마십시오. 그리고 YES로 설정해도 문제가 해결되지 않았습니다.
Kalle

1
정의에 의해 한 줄인 UITextField는 줄 바꿈과별로 관련이 없습니다. 따라서 문서에 명시된 바와 같이 Return / Done 버튼을 누르는 과정에 대한 자세한 내용입니다.
mvds

모든 것을 올바른 방법으로 연결 했습니까? 당신은 넣어 가지고 NSLog("tf %x / method ...",textField);모든 위임 기능에?
mvds

대리자 함수는 적절하게 호출되며 대리자가 제대로 설정되지 않은 경우에는 그렇지 않습니다. 그리고 NSLog는 EXC_BAD_ACCESS를 제공합니다. 또한 XCode에서 호환되지 않는 유형이라고 경고합니다.
Kalle

도 미안, 저 자신을 보았을 것입니다. 형식화가 시작되면이 NSLog의 결과로 위의 답변을 업데이트했습니다.
Kalle

0

UINavigationController에 문제가있는 사람들은 비슷한 질문에 대한 내 대답을 참조하십시오 : https : //.com/a/10507689/321785

편집 : 나는 UIViewController의 카테고리에 관한 파스칼의 의견과 달리 Miha Hribar의 솔루션이 개선되었다고 생각합니다 (결정이 필요한 곳에서 이루어지기 때문에).


0

완벽한 솔루션은 아니지만 작동합니다
[self.view endEditing : YES];
모달을 표시하기 위해 버튼이나 제스처가 구현 된 곳에서


0
Swift 4.1:
extension UINavigationController {
   override open var disablesAutomaticKeyboardDismissal: Bool {
      return false
   }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.