ビュー内のテキスト フィールド間のタブ順序を設定する方法 (IB またはコードのいずれか) はありますか?
ここで注意していただきたいのは、リターン (または「次へ」) ボタンが押された後の次のフォーム フィールドについて話しているのではないということです。多くの Bluetooth キーボードにはタブ キーがあり、フィールドをまったく異なる順序で循環するようです。私の場合、この順序はビュー内のフィールドの位置や、フィールドが追加された順序と一致しません。xib ファイルを手動で変更して NSNextKeyView を変更しても、違いはないようです。
この順序を変更する方法を知っている人はいますか?
ベストアンサー1
@sprocketの回答は、少しだけ役に立った。何かがすぐに使えるからといって、より良い方法を考えるのをやめるべきではない。正しい方法-- 何かをすること。彼が気づいたように、その動作は文書化されていないが、ほとんどの場合私たちのニーズに適合します。
しかし、これは私にとって十分ではありませんでした。RTL 言語を考えてみると、タブは依然として左から右に移動します。言うまでもなく、動作はシミュレータごとにまったく異なります (デバイスはタブで最初の入力にフォーカスしません)。しかし最も重要なのは、Apple の文書化されていない実装では、ビュー階層に現在インストールされているビューのみが考慮されるように見えることです。
テーブル ビュー形式のフォームを考えてみましょう (しゃれではありません)。各セルには 1 つのコントロールが保持されるため、すべてのフォーム要素が同時に表示されるとは限りません。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];
}
事前に表示されているオフスクリーンのレスポンダをスクロールするための追加ロジックが適用される場合があります。
このアプローチのもう1つの利点は、表示したいすべての種類のコントロール(UITextField
sなど)をサブクラス化する必要がなく、代わりにコントローラーレベルでロジックを管理できることです。正直に言うと、適切な場所そうするために。