Клавиатура iPad не будет отключена, если стиль представления модального ViewController - UIModalPresentationFormSheet

Примечание.

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

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

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

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

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

...

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

РАБОТАЕТ

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

person Kalle    schedule 30.07.2010    source источник
comment
Следующий вопрос SO, похоже, имеет ту же проблему, но нет ответов: stackoverflow.com/questions/3019709/   -  person Kalle    schedule 02.08.2010
comment
+1 Спасибо за отличное объяснение. Но где мне разместить этот метод? Кажется, не работает там, где я создаю код для представления контроллера модели ...   -  person Lorenzo B    schedule 26.06.2012
comment
Он должен быть в самом классе контроллера модального представления.   -  person Kalle    schedule 26.06.2012
comment
Спасибо. Понятно. Я решил поместить его в категорию UINavigationController класса. Ваше здоровье.   -  person Lorenzo B    schedule 27.06.2012
comment
Я очень признателен тебе за этот вопрос. Я был удивлен, что resignFirstResponder выполняется, но клавиатура все еще отображается. Мой сценарий (презентацияFormSheet с управлением навигацией) точно такой же, как и ваш. Благодаря тонну!!   -  person sErVerdevIL    schedule 09.01.2013


Ответы (12)


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

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}
person Sebastian H    schedule 31.03.2011
comment
Да, начиная с 4.3, похоже, что это так. Обновлю вопрос. Спасибо! - person Kalle; 31.03.2011
comment
Это необходимо добавить в контроллер навигации. - person pottedmeat; 24.09.2013
comment
Да, работает при перезаписи в NavigationController. Это единственное, что у меня действительно сработало. - person James Laurenstin; 01.12.2013
comment
Спасатель жизни! Почему Apple делает такие вещи? Конечно, по умолчанию он должен быть НЕТ и позволять нам изменять его, если мы действительно хотим - person SomaMan; 24.06.2014
comment
Не работает с производным классом UIViewController, disablesAutomaticKeyboardDismissal никогда не вызывается - person Jorge Arimany; 16.10.2015

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

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

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

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

ОБНОВЛЕНИЕ:

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

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

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

person Mike Weller    schedule 02.08.2010
comment
пауза Вау, ладно. Большое спасибо за внимание. Блин Apple .. :( - person Kalle; 02.08.2010
comment
Вы отправляли отчет об ошибке в Apple? Я сделал это под ID # 8384423. Я также отправил образец приложения, чтобы воспроизвести поведение. - person Shaggy Frog; 02.09.2010
comment
MishieMoo: здорово! По крайней мере, рад, что Apple это признает. - person Kalle; 16.09.2010
comment
Вау, это дебил. Вы могли подумать, что они создадут гибкое решение, которое позволит нам соответствовать вариантам использования нашего клиента ... но вместо этого они создают вариант использования для клиента, которого даже не знают! : S - person PostCodeism; 26.11.2010
comment
Начиная с iOS 4.3, теперь есть метод disablesAutomaticKeyboardDismissal, который устраняет эту проблему. - person Kalle; 31.03.2011
comment
Я пытаюсь отключить метод DisablesAutomaticKeyboardDismissal, но проблема все еще не решена. Как ее решить? - person R. Dewi; 21.09.2011
comment
К сожалению, это решение снова не работает в iOS 6 :-( - person Snips; 27.10.2012
comment
@Snips: вам нужно создать подкласс UINavigationController, который переопределяет disablesAutomaticKeyboardDismissal для возврата NO и использовать его в качестве контроллера навигации, когда вы представляете лист модальной формы. См. Ответ @ miha-hribar ниже. - person Pascal; 27.10.2012

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

person Miha Hribar    schedule 10.05.2011
comment
+1, наконец, я вижу выделенную недостающую информацию для этой проблемы: чтобы исправить эту проблему, нужно переопределить disablesAutomaticKeyboardDismissal из UINavigationController, а не собственный контроллер представления. - person DarkDust; 26.10.2011
comment
Отлично! Как раз то, что мне было нужно. Спасибо. - person Justin; 02.12.2011
comment
Идеально. Не ясно из официальных документов, но имеет смысл из-за того, что UINavigationController находится в цепочке респондентов. Отличный ответ. Спасибо! - person imnk; 17.04.2012
comment
Это знание сразу устранило мою проблему. Спасибо! - person Mark; 19.05.2012
comment
Я представляю модальный диалог из UISplitViewController. Я пробовал приведенный выше код, но заменил UISplitViewController на UINavigationController, но он по-прежнему не работает. Должен ли этот метод работать и с UISplitViewController? - person Snips; 27.10.2012
comment
Благодарим за предоставленное решение, которое действительно работает, с кратким и понятным объяснением. - person Jono; 20.01.2013
comment
Я создал эту категорию и импортировал ее в контроллер представления, который я буду использовать. что теперь? мне нужно что-то переопределить или добавить какой-либо код, чтобы убрать клавиатуру в viewController? - person HusseinB; 10.04.2013
comment
Не рекомендуется реализовывать в категории повторяющийся метод. Вы никогда не можете быть уверены, какая реализация будет вызвана, поэтому в лучшем случае можно ожидать противоречивого поведения. Лучше унаследовать от UINavigationController и переопределить метод в вашем пользовательском классе. - person sean woodward; 19.04.2013
comment
Чувак, как я не подумал об этом решении ?! Обычно, как сказал Шон, в этих случаях лучше использовать подкласс ... - person Natan R.; 18.07.2013

Я решил эту проблему, применив стиль презентации 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];
person azdev    schedule 15.12.2010
comment
Хммм ... это не совсем правильно ... изменение размера заставляет модальное окно рисовать забавно ... это как будто он сжимает содержимое, чтобы поместиться в поле нового размера или что-то в этом роде ... все выглядит забавно. :( - person toofah; 07.01.2011
comment
У этого также есть проблемы с вращением ... если вы вращаете, пока этот модальный экран работает, он будет сжиматься / увеличиваться, как если бы это был полный просмотр страницы - person toofah; 07.01.2011
comment
toofah, я отредактировал код, чтобы решить проблему сжатия / роста при вращении; просто вопрос предоставления супервизору гибкого верхнего и нижнего поля. Я не уверен, что вижу другое поведение. - person azdev; 08.01.2011
comment
это работает только до тех пор, пока вы не добавляете другой вид поверх этого. Потому что, когда вы закрываете представление, помещенное над представленным представлением UIModalPresentationPageSheet, оно возвращается к исходному размеру. - person V1ru8; 07.04.2011
comment
Это сработало. Но слово в поле зрения выглядит немного размытым. Не знаю почему. - person jeswang; 23.08.2012
comment
Обычно я использую то же решение для изменения размера модального представления. Но я понимаю, что это не работает для iOS 6. Представление всегда застревает в верхней части родительского представления. Любое решение ?? Благодарность - person Frade; 03.12.2012

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

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

-Адам

person Adam    schedule 09.12.2010

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

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

person Maciej Swic    schedule 06.03.2012

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

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

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

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

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

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

person Mike Gledhill    schedule 22.06.2015

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

person Neal L    schedule 01.08.2010
comment
Я сам установил его вручную, и вызываются методы делегата, так что да. - person Kalle; 01.08.2010

возможно не вернет NO, но YES. Так что это может уйти.

И у вас тоже textFieldShouldEndEditing возвращается ДА?

И почему вы стреляете [nextResponder becomeFirstResponder] ?! извините, я понял

У меня также есть несколько UITextView, для всех которых свойство "editable" установлено на FALSE.

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

person mvds    schedule 30.07.2010
comment
NO = не вставлять новую строку, насколько я могу судить. И установка ДА не исправила. - person Kalle; 30.07.2010
comment
Я думаю, что UITextField, являясь одной строкой по определению, мало что делает с символами новой строки. Так что это больше касается обработки нажатия кнопки Return / Done, как указано в документации. - person mvds; 30.07.2010
comment
Вы уверены, что все правильно подключили? Вы добавили NSLog("tf %x / method ...",textField); во все функции-делегаты? - person mvds; 30.07.2010
comment
Что ж, функции делегата вызываются соответствующим образом, и их не было бы, если бы делегат не был настроен должным образом. И NSLog выдает EXC_BAD_ACCESS. Также предупреждает меня, что это несовместимый тип в XCode. - person Kalle; 01.08.2010
comment
Ооо. Извини, я должен был сам это увидеть. Я обновил ответ выше, добавив результаты этих NSLogs, поскольку форматирование будет происходить само в сообщении. - person Kalle; 01.08.2010
comment
поместите несколько NSLog в if, чтобы увидеть, что именно происходит. см. мой обновленный ответ, кстати. - person mvds; 01.08.2010
comment
Разве вы не можете просто заархивировать все это и куда-нибудь выложить? Я хочу верить, что все в порядке, но это не работает, но я хотел бы увидеть это своими глазами ... - person mvds; 01.08.2010
comment
Не могу, потому что это рабочий проект и все такое, но я сделаю (и я должен сделать это в любом случае) создать новый проект и объединить эту его часть. Предположительно он будет РАБОТАТЬ, но если это не так, я могу опубликовать этот проект. Но дайте мне день или около того, чтобы это сделать. Обновит ответ и тому подобное, когда это будет сделано. - person Kalle; 01.08.2010
comment
Хм! Работая над включением этого в отдельный проект, я понял следующее: клавиатура УДАЕТСЯ, если представление НЕ ЯВЛЯЕТСЯ МОДАЛЬНЫМ. Если вид есть, клавиатура остается; если вида нет, клавиатура уходит. Все еще не знаю, как это решить, но через секунду опубликую две версии выше в своем ответе ... - person Kalle; 02.08.2010
comment
Я обновил ответ выше и немного очистил его. Таким образом, следующая строка вызывает проблему: navigationController.modalPresentationStyle = UIModalPresentationFormSheet; - если сниму, клавиатура закроет штраф. Могу только предположить, что это ошибка. - person Kalle; 02.08.2010


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

person Tanuj Jagoori    schedule 08.05.2015