При назначении фокуса с помощью startFirstResponder в UISearchController UISearchBar клавиатура не появляется
Я потратил немало времени на поиск в Интернете и разговоры с другими разработчиками об этой проблеме безрезультатно. Точная проблема описана в этом сообщении SO (Фокусировка на UISearchBar, но клавиатура не отображается), хотя ей много лет.
Недавно я переключился с использования устаревшего UISearchDisplayController и UISearchBar в IB и переключился на UISearchController с помощью кода для iOS8.
Проблема, которую я получаю, заключается в том, что фокус назначается правильно (вы можете сказать, потому что кнопка отмены анимируется справа от строки поиска после загрузки вида), однако клавиатура не отображается.
Вот код, который у меня есть.
.h
@property (nonatomic, strong) UISearchController *searchController;
.m
- (void)viewDidLoad {
[super viewDidLoad];
...
[self initializeSearchController];
....
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.searchController setActive:YES];
[self.searchController.searchBar becomeFirstResponder];
}
- (void)initializeSearchController {
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.delegate = self;
self.searchController.searchBar.delegate = self;
[self.searchController.searchBar sizeToFit];
[self.tableView setTableHeaderView:self.searchController.searchBar];
self.definesPresentationContext = YES;
}
То, что я пробовал до сих пор.
-
Я пробовал называть startFirstResponder с задержкой в 0,2 секунды, как это было предложено в другом сообщении SO.
-
Я установил точку останова в viewDidAppear и проверил, что оба self.searchController и self.searchController.searchBar являются действительными объектами, ни nil.
-
Я пробовал соответствовать UISearchControllerDelegate и использовал следующий фрагмент кода
здесь:
- (void)didPresentSearchController:(UISearchController *)searchController {
//no matter what code I put in here to becomeFirstResponder, it doesn't
//matter because this is never called, despite setting the
//self.searchController.delegate = self AND
//self.searchController.searchBar.delegate = self.
}
-
Я создал новое представление с нуля в раскадровках и вместо этого перешел к этому, чтобы убедиться, что у меня не осталось старого остатка SearchBar. Это тоже не сработало.
-
Я тестировал это только на реальном устройстве (iPhone 6), и это не проблема симулятора, не отображающая клавиатуру.
У меня нет идей, и я видел все вопросы и ответы, связанные с этим в Интернете. Ничего не работает.
Чтобы еще раз прояснить, что происходит, searchBar правильно становится первым ответчиком, кнопка отмены справа от него оживляет на экране, доказывая это, но клавиатура не появляется, и курсор не мигает в searchBar.
Ответы
Ответ 1
Ваш код выглядит нормально. То, что вы описываете, - это не нормальное поведение.
Первое, что вы можете сделать, это создать новый проект с помощью только функции UISearchController
и посмотреть, как это происходит. Вы можете отредактировать свой вопрос, чтобы у нас было лучшее представление.
Вот хороший пример того, как реализовать UISearchController
здесь: Sample-UISearchController
Добавление:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.searchController.searchBar becomeFirstResponder];
}
to MasterViewController_TableResults.m
дал ожидаемые результаты, и клавиатура появилась при запуске на iPad и iPhone с iOS 8.3.
Вы можете просмотреть этот проект и посмотреть, что вы сделали по-другому,
Edit:
По-видимому, если [self.searchController setActive:YES]
вызывается до becomeFirstResponder
, клавиатура не будет отображаться. Интересно, если это ошибка или нет.
Ответ 2
Имел такой же раздражающий вопрос.
Вы могли бы подумать, что, установив SearchController как активный, оба будут представлены контроллером поиска и клавиатурой. К сожалению, это только первая часть.
Мое решение
-
В режиме просмотраDidAppear активный контроллер поиска:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
resultSearchController.active = true
}
-
после того, как он активен, в didPresentSearchController сделайте как первый ответчик
func didPresentSearchController(searchController: UISearchController) {
searchController.searchBar.becomeFirstResponder()
}
Ответ 3
Рабочее решение Swift 3.0 (iOS 10):
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
searchController.isActive = true
DispatchQueue.main.async { [unowned self] in
self.searchController.searchBar.becomeFirstResponder()
}
}
Ответ 4
В iOS 9 я нашел достаточно для задержки becomeFirstResponder()
следующего цикла цикла:
func focusSearchField() {
searchController?.active = true
// skipping to the next run loop is required, otherwise the keyboard does not appear
dispatch_async(dispatch_get_main_queue(), { [weak self] in
self?.searchController?.searchBar.becomeFirstResponder()
})
}
Ответ 5
В iOS 10 мне пришлось запустить код в методе делегата в основном потоке. Сначала я установил активный в YES в viewDidAppear,
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self.searchController setActive:YES];
}
а затем в методе делегата:
- (void)didPresentSearchController:(UISearchController *)searchController
{
dispatch_async(dispatch_get_main_queue(), ^{
[searchController.searchBar becomeFirstResponder];
});
}
Ответ 6
Рабочее решение: -
Не используйте [self.searchController setActive: YES] перед тем, как стать первым_пользователем.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
// [self.searchController setActive:YES];
[self.searchController.searchBar becomeFirstResponder];
});
});
}
Ответ 7
Решение, которое будет работать, выглядит следующим образом:
1.Нажмите ViewDidLayoutSubviews
в контроллере представления, в котором вы показываете UISearchController
2. Переверните ViewDidLayoutSubviews
и внутри него сделайте первый ответчик поиска.
Протестировано на iOS > 9.0
Предостережение: поставьте нулевую проверку перед тем, как сделать ее первым ответчиком следующим образом
if((searchController != null)&&(searchController.SearchBar != null))
searchController.SearchBar.BecomeFirstResponder();
Это потому, что ViewDidLayoutSubviews
также вызывается при нажатии кнопки отмены.
Это сработало для меня в Xamarin.
Ответ 8
У меня были проблемы с UISearchBar, не отображающим клавиатуру при выполнении
[searchBar becomeFirstResponder];
Просматривая в сети, я нашел этот поток на веб-сайте разработчика Apple
что помогло мне обнаружить, что клавиатура не откроется, если у вас нет ключа.
Приложение, над которым я работаю, делает что-то вроде этого:
- Окно A (KeyWindow)
- сделать некоторые вещи
- открыть окно B (KeyWindow)
- сделать некоторые вещи
- закрыть окно B (отменить KeyWindow)
Мне просто нужно было
[[[[UIApplication sharedApplication] windows] firstObject] makeKeyWindow];
после отставки окна B и никаких проблем с клавиатурой.
Ответ 9
Это также может быть связано с настройками Simulator. Просто отключите Hardware → Keyboard → "Connect Hardware Keyboard".
Для получения дополнительной информации: UISearchBar не показывает клавиатуру при нажатии
Ответ 10
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.searchController setActive:YES];
}
//and then in the delegate method:
- (void)didPresentSearchController:(UISearchController *)searchController
{
dispatch_async(dispatch_get_main_queue(), ^{
[searchController.searchBar becomeFirstResponder];
});
}
//The above works for me in addition to this I had to add:
-(void)viewWillDisappear:(BOOL)animated {
[searchController setActive:NO];
}