3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

iOS Keyboard ExtensionでadjustTextPositionするときのお作法

Posted at

iOS Keyboard Extensionでカーソルを移動させるにはadjustTextPosition(byCharacterOffset:Int)を使います。ドキュメントにはバッチリ

To move the insertion point in the text input view, use the adjustTextPosition(byCharacterOffset:) method. For example, if you want to implement a forward delete action, move the insertion position forward by one character then delete backwards:

// Move the text insertion position forward 1 character (一文字分前に進める)
textDocumentProxy.adjustTextPosition(byCharacterOffset: 1)

と書いてありますが、罠です。なかなか気付きにくいところだと思うので共有しておきます。

この通りに実装するとこんな挙動になります。
ezgif-5-786edace6467.gif

「あいうえお」まではうまく動いていますが、漢字や絵文字に至ったあたりからどうも様子がおかしいですね。

解決方法

どうやらこのメソッドはutf16とした時の文字数で「一文字分」を数えています。ということで、実行前に進行方向の文字をチェックして、それからadjustTextPositionしましょう。

func getActualOffset(count: Int)->Int{
    if count>0{
        if let after = textDocumentProxy.documentContextAfterInput{
            if after == ""{
                return 1   //一文字前に改行がある場合、after==""となる。
            }
            let left = after.prefix(count)
            return left.utf16.count
        }else{
            return 1
        }
    }else if count<0{
        if let before = textDocumentProxy.documentContextBeforeInput{
            let right = before.suffix(-count)
            return -right.utf16.count
        }else{
            return -1
        }
    }else{
        return 0
    }
}

let offset = getActualOffset(count: 1) //正確なoffsetを取得する
textDocumentProxy.adjustTextPosition(byCharacterOffset: offset) //実行する

これで意図した通り動作します。
ezgif-5-410ac0a2f5c8.gif

気付きづらいところに潜んでいる落とし穴なので、くれぐれもお気をつけください。

3
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?