GetFirstResponder работает в viewDidAppear, но не работает в viewDidLoad

В моем приложении есть модальный контроллер просмотра, включая панель поиска. Когда появится представление, я хочу, чтобы панель поиска была сфокусирована. Я пробовал [self.searchBar becomeFirstResponder] в viewDidLoad, но это не сработало. Позже я положил его в viewDidAppear, он сработал. Но с этим обходным путем существует заметная задержка. (после того, как представление полностью появилось, клавиатура начала появляться)

Я могу гарантировать, что будут вызваны как viewDidAppear, так и viewDidLoad.

Что делать, если я хочу, чтобы панель поиска мгновенно сфокусировалась с представлением?

(Я использую StoryBoard)

Следуя ответам, я попытался поместить код в viewWillLoad, но все равно не работал. (в viewWillLoad, self.searchBar.window равно nil)

Ответ 1

Возможно, он не работает в viewDidLoad, поскольку представление еще не добавлено в иерархию представлений. Но согласно документации на яблоко beFirstResponder следует вызывать только на объектах, прикрепленных к UIWindow:

However, you should only call it on that view if it is part of a view hierarchy. 
If the view’s window property holds a UIWindow object, it has been installed 
in a view hierarchy; if it returns nil, the view is detached from any hierarchy.

Итак, я полагаю, лучшее место для достижения необходимого поведения - это поместить вызов в метод viewWillAppear.

Обновить.

Итак, в представлении контроллера viewWillAppear еще не подключен к UIWindow... он только уведомляет, что этот вид будет добавлен для просмотра иерархии

Это может быть несколько сложнее, но вы можете сделать небольшую задержку в viewWillAppear:

 - (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    double delayInSeconds = 0.05;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^{ 
        make first responder here
    });
 }

Но я считаю, что должно быть лучшее решение

Ответ 2

все объекты IBOutlet загружаются в viewDidLoad, если вы вызываете метод в viewDidLoad, тогда это действие не выполняется, потому что перед тем, как объекты загружаются, мы не можем ничего сделать, чтобы почему-то писать этот код в

-(void)viewWillAppear:(BOOL)animated{
//write here
} 

тогда он отлично работает.

Ответ 3

Создание текстового поля/просмотра первого ответчика должно выполняться после всех анимаций UIViewController, которые происходят, когда просмотр загружается и отображается. Поэтому лучшим местом является viewDidAppear.

Ответ 4

Это поможет:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.quantifyTextField becomeFirstResponder];
    });
}

Ответ 5

Напишите viewWillAppear instad viewDidAppear/viewDidLoad.

Так как метод viewWillAppear является вызовом во время представления, будет отображаться (в процессе), для получения дополнительной информации about viewWillAppear прочитать этот официальный документ.

- (void)viewWillAppear:(BOOL)animated
{
    [self.searchBar becomeFirstResponder];
    [super viewWillAppear:animated];
}

Ответ 6

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

Не забудьте установить делегат текстового поля в nil в viewWillDisappear, иначе клавиатура больше не будет отображаться, если вы поместите/отклоните контроллер вида, не закрывая клавиатуру.