Я бы хотел уточнить @ ответ звездочки , касающийся той же проблемы.То, что что-то работает из коробки, не означает, что вы должны перестать думать о лучшем способе - или даже правильном способе - что-то делать.Как он заметил, поведение недокументировано, но большую часть времени соответствует нашим потребностям.
Хотя этого было недостаточно для меня.Представьте, что язык RTL и вкладки будут по-прежнему вкладываться слева направо, не говоря уже о том, что поведение полностью отличается от симулятора к устройству (устройство не фокусирует первый ввод на вкладке).Однако самое важное то, что недокументированная реализация Apple, похоже, рассматривает только представления, установленные в настоящее время в иерархии представлений.
Представьте себе форму в форме (без каламбура) табличного представления.Каждая ячейка содержит один элемент управления, поэтому не все элементы формы могут быть видны одновременно.Apple просто переключится назад, как только вы дойдете до самого нижнего (на экране!) Элемента управления, вместо того, чтобы прокручивать дальше вниз.Такое поведение определенно не то, что мы хотим.
Итак, вот что я придумала.Ваша форма должна управляться контроллером представления, а контроллеры представления являются частью цепочки респондента.Таким образом, вы совершенно свободны в реализации следующих методов:
#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), но вместо этого можете управлять логикой на уровне контроллера, где, давайте будем честными, правильное место для этого.