はじめに
これまでは主にデスクトップ向けのIMEを扱ってきましたが、本日はモバイル向けのOSであるiOSのIME APIについてです。
(UWPは例外的にモバイルも含むプラットフォームでしたが)
モバイルでも日本語入力という枷からは逃れることはできないので、iOSにもIME APIが用意されています。
とはいえ、サードパーティのIME自体は比較的最近(iOS 8)までは存在しませんでしたね。
UITextInput
iOSのIME APIの中心となるのがUITextInput
なのは間違い無いのですが、その実装はひどく面倒なものになっています。
UITextInput
はUIKeyInput
を、UIKeyInput
はUITextInputTraits
を、UITextInputTraits
はNSObjectProtocol
を継承しています。
-
UIView
,UITextInput
を継承したViewを作るbecomeFirstResponder()
canBecomeFirstResponder: Bool = true
-
基本実装: macOS編の
NSTextInputClient
と同様の実装をこちらでも行う -
UITextPosition
を継承したテキストの位置を保持するクラスを作る -
TextRange
を継承したテキストの範囲を保持するクラスを作る - 3.と4.で作ったクラスのインスタンス同士の比較関数を作る
-
UITextPosition
同士を比較したり、UITextPosition
がTextRange
に含まれるかを返したりする関数 - (この辺はWindowsのIAnchorに近いものがある)
-
- 音声入力周りの実装がある
- 音声入力中のPlaceholderを作って返す
- Placeholderのディスプレイ上の位置を返す
- 不要になったPlaceholderを削除する
- 結果を挿入する
おわりに
iOSのIME APIは基本実装自体はmacOSとほとんど変わらないのですが、とにかく周辺実装がたくさん増えてて大変という感じです。
一番大変そうなのがvar tokenizer: UITextInputTokenizer
の実装ですね。
テキストの切れ目などをいい感じに返すやつです。
(多分サードパーティのキーボードとかで文節単位で移動できたりするのはここを叩いてるのかな)
縦書きに関するメモ
縦書きに関連するのはfunc selectionRects(for range: UITextRange) -> [Any]
で返すUITextSelectionRect
にisVertical: Bool
がある程度です。
来年にはiOS版のTATEditorも作るので、そのときに何かわかるかなあと祈ってます。
(標準のキーボードだと活用されてなさそうな気が……?)