多言語対応アプリ開発でつまづいたiOSキーボード問題

多言語対応アプリ開発でつまづいたiOSキーボード問題

はじめに

今回開発していたアプリは、日本語・英語・中国語など9ヶ国語に対応していました。多言語対応というと翻訳やレイアウト調整が注目されがちですが、実務では入力体験の難易度も一気に上がります。端末の言語設定やキーボード(標準/サードパーティ)、入力モード(英字・数字・記号)といった条件の組み合わせが増え、ログインのような基本動線でも想定外のことが起きやすくなるためです。

その中で遭遇したのが、iOSのログイン画面において、パスワード入力中に数字や記号を入力しようとすると、入力モードが英字に戻ってしまうという問題でした。

調査を始めた当初は、

  • サードパーティ製キーボードの不具合
  • React NativeのTextInputコンポーネントにおけるsecureTextEntryによる制約

といった「いかにも原因っぽいもの」に引っ張られ、結果的に遠回りをすることになりました。

最終的に分かったのは、
secureTextEntryではなく、inputAccessoryViewIDが直接のトリガーだった
ということです。

この記事では、多言語対応アプリという前提のもとで、

  • どんな背景・条件で起きていたのか
  • なぜ secureTextEntryが原因だと思い込んだのか
  • どのように切り分けて真因に辿り着いたか

を、間違った仮説も含めて学習ログとしてまとめます。

背景と事象の概要

対象は、React Native で実装した iOS 向けログイン画面です。

画面には次の2つの入力欄があります。

  • email / username 入力欄(非secure)
  • パスワード入力欄(secureTextEntry={true}

また、パスワード欄には独自の入力補助UIを出す目的で inputAccessoryViewID を設定していました。

この状態で、サードパーティ製キーボード(Gboard / Simeji など)を有効にしていると、
次のような挙動が発生しました。

起きていた事象(観測された挙動)

  • iOSのみで発生(Androidでは未確認)
  • パスワード入力欄にフォーカスすると、キーボードが不安定になる
  • 数字・記号入力に切り替えても、入力しようとすると英字に戻る
  • 入力モードが維持されないように見える

見た目だけを見ると、「サードパーティ製キーボード × secureTextEntry の相性問題」に見える挙動でした。

調査の方針:まず「再現条件」から原因候補を絞る

キーボード周りの不具合は要因が多いため、最初に「どの条件が揃うと起きるのか」を整理しました。

すると現象は、ざっくり次の2つの特徴が見えてきました。

  • サードパーティ製キーボードが端末に存在すると起きやすい
  • secureTextEntry のパスワード入力中にだけ起きる

この時点ではまだ真因は分からないものの、「怪しそうな方向性」は大きく2つに絞れます。

そこで、いったん次の2つを仮説として立て、順番に検証していくことにしました。

仮説① サードパーティ製キーボードが悪い?

Gboard / Simeji を無効にすると症状が出ないため、
最初は「サードパーティ製キーボード固有の問題」ではないかと考えました。

最初に疑ったのは、サードパーティ製キーボードそのものです。

現象:

  • サードパーティ製キーボードが登録されている端末だけで発生する
  • 無効化すると再現しなくなる

この観測だけを見ると、「サードパーティ製キーボードが原因」に見えます。

しかし、実際には、

  • secureTextEntry により、入力時は 必ず標準キーボードが使われている
  • サードパーティ製キーボード自体が入力に関与していない

という状態でした。

仮説①の整理

  • サードパーティ製キーボードそのものが直接原因ではない
  • 「登録されていること」が前提条件になっているだけ
  • その存在によって、iOS の キーボード切替・制御フローが変わり、問題が顕在化していた

という位置づけが正しい整理でした。

仮説② secureTextEntry の制約が原因?

次に疑ったのが secureTextEntry です。

そう考えた理由はシンプルで、

  • secureTextEntry={true} のときだけ発生
  • 非secureな入力欄では起きない
  • secureTextEntry ではカスタムキーボードが使えない仕様がある[1]

ここで「secureTextEntry × キーボード切り替え」がかなりそれっぽい原因に見えてしまいました。

さらに、次のような観測がありました。

  • 同一画面に secure / non-secure の TextInput があると再現しやすい
  • 非secure欄を一時的に消すと症状が落ち着く
  • 表示専用Textに切り替える回避策が効く

この時点で、「secure と non-secure が混在し、フォーカス遷移するとキーボード状態が壊れる」という もっともらしいストーリーを作ってしまいました。

違和感と切り分けのやり直し

ただし、実装を続ける中で違和感が残りました。

  • UI構成を変えないと直らないのは不自然
  • secureTextEntry だけが原因なら、もっと単純な再現条件になるはず
  • なぜ「数字入力だけ」が壊れるのか説明しきれない

そこで、TextInput に付与している設定を1つずつ外す という原点に戻りました。

真因:inputAccessoryViewID を外すと再現しない

問題のコードは以下でした。

<TextInput
  secureTextEntry
  inputAccessoryViewID="passwordToolbar"
/>

ここで inputAccessoryViewID を削除したところ、

  • 英字に戻る現象が再現しなくなった
  • サードパーティ製キーボードでも安定した
  • secureTextEntry を使っていても問題なし

つまり、 直接の原因は secureTextEntry ではなく、inputAccessoryViewID が絡んだ入力ビューの挙動だと判断しました。

なぜ inputAccessoryViewID が原因になり得るのか

公式ドキュメントから確認できること

  • secureTextEntry ではカスタムキーボードが使えず、
    フォーカス時に システム標準キーボードへ切り替わる [1]
  • inputAccessoryViewID は、TextInput が first responder の間、
    キーボード上部に表示される補助ビューを紐づける仕組み[2]
  • iOSは first responder の状態に応じて、
    入力ビュー(キーボード+アクセサリ)を再構築できる設計 [3]

ここからの推察(※公式ドキュメントには明記されていない)

  • inputAccessoryViewID があると、フォーカス取得やキーボード表示時に 入力ビュー再構築が発生しやすくなる
  • キーボードの「英字 / 数字 / 記号」といった入力面の状態は、再構築時に初期化される可能性がある
  • secureTextEntry による「カスタム → 標準キーボード切替」と組み合わさり、
    入力面が頻繁にリセットされる状態遷移が発生した結果、「数字を押そうとすると英字に戻る」ように見えたと考えられる

実務的な回避策と現実的な判断

今回の現場で現実的だった選択肢は次の通りです。

  • パスワード欄では inputAccessoryViewID を使わない(最優先で検討)
  • 入力補助UIが必要なら、
    • キーボード上ではなく画面内に置く(固定UI)
    • もしくはキーボード高さに追従する独自コンポーネントで代替する
  • 「まずは直す」なら、inputAccessoryViewID を外して影響範囲を最小化し、別のUX案を後追いで検討する

「アクセサリが便利だから付ける」が、特定条件でログイン体験を壊すなら、ここは割り切った方が早いです。

まとめ

今回の現象は見た目が紛らわしく、secureTextEntry やサードパーティ製キーボードが原因に見えやすい状況でした。さらに回避策が効くと“それっぽい仮説”が補強され、原因候補を追うほど情報が増えて解決から遠ざかります。

そこで「原因を当てにいく」のをやめ、TextInput の設定を1つずつ外して再現条件を絞る検証へ切り替えました。その結果、トリガーが secureTextEntry ではなく inputAccessoryViewID(accessory 周辺)にあると特定でき、実務的な回避策にもつながりました。

似た不具合に遭遇したら、まずは変数を減らして“観測できる状態”を作ってみてください。特に iOS のキーボード問題では、secureTextEntry を深掘りする前に inputAccessoryViewID を含む周辺設定を最小化すると、切り分けが一気に進むことがあります。

原因探しで消耗するより、条件を削って再現性を握る——この切り替えが、次に似た不具合に出会ったときの一番の近道になると感じました。

不具合の解決に時間がかかる場合は、思考を柔軟に切り替えてみるといいかもしれません。

引用元

[1] Apple Developer Documentation – Custom Keyboard
https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/CustomKeyboard.html 

[2] React Native Documentation – InputAccessoryView
https://reactnative.dev/docs/inputaccessoryview 

[3] Apple Developer Documentation – Text and Web Programming Guide for iOS
https://developer.apple.com/library/archive/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/ 

AIエージェントがブラウザを操作:新しいCLIツール agent-browser
Cursor Commands
活用術 ― レビューとPR作成の自動化プロンプト