Решение
В iOS 7 вызов becomeFirstResponder
на _textView
в viewDidLayoutSubviews
работает.
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[_textView becomeFirstResponder];
}
Примечание. Выполнение этого в viewWillLayoutSubviews
также работает.
Объяснение
Прочитайте обсуждение в документации по стать первым респондентом .
Вы можете вызвать этот метод, чтобы сделать объект респондента, такой как представление, первым респондентом. Однако вы должны вызывать его только в этом представлении, если оно является частью иерархии представлений. Если свойство представления window
содержит объект UIWindow
, оно установлено в иерархии представлений; если возвращается nil
, представление отсоединяется от любой иерархии.
При использовании контроллера навигации для вывода на экран пользовательского контроллера представления, self.view.window
по-прежнему nil
к тому времени, когда вызывается viewDidLoad
или viewWillAppear:
. Таким образом, _textView.window
также является nil
в тех же методах, поскольку _textView
является подпредставлением self.view
, то есть они оба находятся в одном и том же окне. Независимо от того, как вы представляете свой пользовательский контроллер представления, self.view.window
(и, следовательно, _textView.window
) также nil
в initWithNibName:bundle:
. self.view.window
устанавливается к тому моменту, когда вызывается viewDidAppear:
, но это слишком поздно, потому что к этому времени навигационный контроллер уже завершил анимацию вывода вида на экран.
self.view.window
также устанавливается к тому времени, когда вызывается viewWillLayoutSubviews
или viewDidLayoutSubviews
, и эти методы вызываются до того, как начинается анимация нажатия контроллера навигации. Вот почему это работает, когда вы делаете это любым из этих методов.
К сожалению, viewWillLayoutSubviews
и viewDidLayoutSubviews
вызывают намного больше, чем просто при первом нажатии навигационного контроллера. Но navigationController:willShowViewController:
и willMoveToParentViewController:
вызывают слишком рано (после viewDidLoad
, но до установки self.view.window
), а navigationController:didShowViewController:
и didMoveToParentViewController:
вызывают слишком поздно (после анимации push).
Единственный другой способ, которым я могу думать, это как-то наблюдать свойство window
_textView
, чтобы вы получали уведомление при его изменении, но я не уверен, как это сделать, поскольку window
readonly
.