Меня удивляет, как много ответов здесь не в состоянии понять одну простую концепцию: навигация по элементам управления в вашем приложении - это не то, что сами представления должны делать. контроллер должен решить, какой элемент управления сделать следующим первым респондентом.
Также большинство ответов относится только к навигации вперед, но пользователи также могут захотеть вернуться назад.
Итак, вот что я придумала. Ваша форма должна управляться контроллером представления, а контроллеры представления являются частью цепочки респондента. Так что вы совершенно свободны для реализации следующих методов:
#pragma mark - Key Commands
- (NSArray *)keyCommands
{
static NSArray *commands;
static dispatch_once_t once;
dispatch_once(&once, ^{
UIKeyCommand *const forward = [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:0 action:@selector(tabForward:)];
UIKeyCommand *const backward = [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:UIKeyModifierShift action:@selector(tabBackward:)];
commands = @[forward, backward];
});
return commands;
}
- (void)tabForward:(UIKeyCommand *)command
{
NSArray *const controls = self.controls;
UIResponder *firstResponder = nil;
for (UIResponder *const responder in controls) {
if (firstResponder != nil && responder.canBecomeFirstResponder) {
[responder becomeFirstResponder]; return;
}
else if (responder.isFirstResponder) {
firstResponder = responder;
}
}
[controls.firstObject becomeFirstResponder];
}
- (void)tabBackward:(UIKeyCommand *)command
{
NSArray *const controls = self.controls;
UIResponder *firstResponder = nil;
for (UIResponder *const responder in controls.reverseObjectEnumerator) {
if (firstResponder != nil && responder.canBecomeFirstResponder) {
[responder becomeFirstResponder]; return;
}
else if (responder.isFirstResponder) {
firstResponder = responder;
}
}
[controls.lastObject becomeFirstResponder];
}
Может применяться дополнительная логика для прокрутки закадровых ответчиков, видимых заранее.
Еще одним преимуществом этого подхода является то, что вам не нужно создавать подклассы всех видов элементов управления, которые вы можете отображать (например, UITextField
s), но вместо этого вы можете управлять логикой на уровне контроллера, где, честно говоря, правильное место для этого.