といってもやることは簡単で、メンション表示全体をUIImage
として、それをNSTextAttachment.image
に設定し、NSAttributedString
に挿入するだけ。

これを、正規表現により抽出した該当箇所に差し替えたり、メッセージ入力中はメンション先の選択時に、カーソル位置に挿入したりすればよい。
NSTextAttachment
として挿入することにより、おのずと1文字扱いされるため、以下のようなメリットがある。
- デリート操作1発でメンション表示を削除できる
- メンション表示の内部にカーソルが入り得ないため、考慮すべきユースケースを減らせる(メンション表示内部で文字入力が行われた、削除操作が行われた、などの考慮)
attachment
のサイズに従い、UILabel
やUITextView
により改行処理が自動的に行われる
上で「メッセージ入力中でのメンション先選択操作」に言及したが、さらっと過ぎるので具体的に触れてみる。これは、よくある以下の選択表示/操作のこと。

今回、これを表示/非表示する条件として、以下を採用した。
- メッセージフィールドに「@」が入力されたらメンション先選択を表示
- これを表示中に、つづけて何かの入力があれば、メンション先選択表示を破棄
- メンション先が選択されたら、表示を破棄
メッセージ入力中に、上述の操作によってメンション先が選択された際、メッセージフィールドにメンション表示(NSTextAttachment
)を挿入するのだが、単純そうに見えてこれにはいくつか落とし穴があった。
まず、一連の操作のトリガーとなった「@」が存在するはずなので、これを削除することを忘れないようにする。そうでないと、@@花子
のようになってしまう。
//カーソル直前の文字(@であるはず)を消すtextView.deleteBackward()
次に、挿入位置の特定。常に文字列末尾にappendするだけなら難はない。しかし現実はそう甘くはない。ユーザーが途中で思い立って、カーソル位置を動かす場合を考慮する必要がある。

textView
上のカーソル位置を特定したり変更したりするのが、思いのほか面倒だった。