IPad-клавиатура не будет отменена, если модальный стиль представления ViewController - UIModalPresentationFormSheet

Примечание:

См. принятый ответ (не самый высокий голос) для решения с iOS 4.3.

Этот вопрос относится к поведению, обнаруженному на клавиатуре iPad, где он отказывается отклоняться, если он показан в модальном диалоге с навигационным контроллером.

В принципе, если я представляю контроллер навигации следующей строкой, как показано ниже:

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

Клавиатура отказывается от увольнения. Если я прокомментирую эту строку, клавиатура уйдет отлично.

...

У меня есть два текстовых поля, имя пользователя и пароль; У пользователя есть кнопка "Далее", а пароль имеет кнопку "Готово". Клавиатура не исчезнет, ​​если я покажу ее в модульном навигационном контроллере.

WORKS

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" как контроллер модального представления, он будет работать. Проблема с навигационным контроллером?

WORKS

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

WORKS

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

Ответ 1

В контроллере представления, который представлен модально, просто переопределите disablesAutomaticKeyboardDismissal для возврата NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

Ответ 2

Это подразделение Apple разработало как "работает по назначению". Некоторое время назад я подал ошибку. Их аргументация заключается в том, что пользователь часто вводит данные в модальную форму, поэтому они пытаются быть "полезными" и держать клавиатуру видимой, где обычно различные переходы в модальном представлении могут вызвать повторное отображение/скрытие клавиатуры.

edit: вот ответ инженера Apple на форумах разработчиков:

Было ли ваше мнение каким-либо образом представлено стилем UIModalPresentationFormSheet? Чтобы избежать частых анимаций "взад-вперед", клавиатура иногда остается на экране, даже когда нет первого ответчика. Это не ошибка.

Это дает много проблем людям (включая меня), но на данный момент, похоже, нет способа обойти это.

UPDATE:

В iOS 4.3 и более поздних версиях теперь вы можете реализовать `-disablesAutomaticKeyboardDismissal 'на вашем контроллере представления, чтобы вернуть NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

Это устраняет проблему.

Ответ 3

Будьте осторожны, если вы показываете модальный код с помощью 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.

Ответ 4

Я решил это, используя стиль презентации 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];

Ответ 5

Если вы переключаете другой модальный дисплей, вы можете заставить клавиатуру исчезнуть. Это не очень красиво, и оно не анимируется, но вы можете заставить его уйти.

Было бы здорово, если бы было исправление, но пока это работает. Вы можете клинировать его в категории на 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

Будьте осторожны с этим, когда вы просматриваетеDidAppear/viewDidDisappear и вызываете все эти методы. Как я уже сказал, это не очень, но работает.

-Adam

Ответ 6

Вы также можете обойти это в универсальном приложении, просто проверив идиому, и если это iPad, вообще не всплывайте клавиатуру и не позволяйте пользователю нажимать все, что они хотят редактировать.

Может быть, не самое приятное решение, но оно очень простое и не нуждается в каких-либо причудливых хаках, которые сломаются со следующей крупной версией iOS:)

Ответ 7

Для тех, у кого проблемы с UINavigationController, см. мой ответ на аналогичный вопрос: fooobar.com/questions/30945/...

Изменить: Я считаю это усовершенствованием решения Михи Хрибара (поскольку решение происходит там, где оно должно), и в отличие от комментария Паскаля относительно категории на UIViewController

Ответ 8

Поместите этот код в свой viewWillDisappear: метод текущего контроллера - это еще один способ исправить это:

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

Ответ 9

возможно, не вернет НЕТ, но ДА. Так что это может исчезнуть.

И у вас есть textFieldShouldEndEditing, возвращающий YES?

И почему вы стреляете [nextResponder becomeFirstResponder]?! жаль, что я вижу сейчас

У меня также есть несколько UITextViews которые все имеют свои "редактируемые" свойство установлено в FALSE.

Можно ли предположить, что ни одно из них не имеет значения tag secondField.tag+1? Если это так, вы говорите им, чтобы они стали первым ответчиком, вместо того, чтобы уволить первого ответчика. Может быть, поместить некоторые NSLog() в структуру if.

Ответ 10

Я уверен, что вы посмотрели на это, но вы уверены, что ваш класс контроллера правильно подключен как делегат UITextField, правильно?

Ответ 11

может быть не идеальным решением, но работает [self.view endEditing: YES],
где бы ни была ваша кнопка или жест, чтобы представить модальные

Ответ 12

Я обнаружил, что disablesAutomaticKeyboardDismissal и добавление функции disablesAutomaticKeyboardDismissal не работает для моего UITextField в модальном диалоговом окне.

Экранная клавиатура просто не исчезнет.

Мое решение состояло в том, чтобы отключить все элементы ввода текста в моем диалоговом окне, а затем снова включить соответствующие части через секунду.

Кажется, что когда iOS видит, что ни один из элементов управления UITextField не включен, тогда он избавляется от клавиатуры.

Ответ 13

Swift 4.1:
extension UINavigationController {
   override open var disablesAutomaticKeyboardDismissal: Bool {
      return false
   }
}