Placeholder 付き UITextView

UITextView って UITextField みたいに Placeholder がないんですね。つい先日まで気づきませんでした。必要とするようなシチュエーションがないとかそのような UI が iOS 的にナシなのかなぁと思っていたらカレンダーアプリのイベント追加画面で Apple 自身が実装してました。しょうがないので作りました。良かったら使ってみてください。CSTextView から CSNPlaceholderTextView に名称を変更しています。

CSNPlaceholderTextView

CSNPlaceholderTextView

特徴

  • 挙動は Calendar.app の イベント追加画面 (EKEventEditViewController)のメモの部分に似せている
  • placeholder の表示位置は Caret の位置に自動調整
  • placeholder の font は textView 側の font プロパティに連動
  • UITextView のリプレイスとして使えるように UITextViewDelegate を汚染しない

ということで、Placeholder として使っている Label の textColor は UITextField の placeholder プロパティの説明にあるように

The placeholder string is drawn using a 70% grey color.

な色にしてあったり、UITextViewDelegate を汚染しないように UITextiView が準拠している UITextInput プロトコルのメソッドをオーバーライドするようにして表示位置や出し入れを調整しています。

ハマったのはplaceholder の表示の On/Off を

- (CGRect)caretRectForPosition:(UITextPosition *)position

だけでやっていましたが、入力済みのテキストを Cut してから Undo Cut して Undo Typing したあとに placeholder が消えないことでした。

- (UITextRange *)selectedTextRange

メソッドはこの問題の動作でも呼ばれることがわかったのでここでも On/Off を行うことで回避しました。ただ、この方法が UITextInput とかのテキスト入力系 の振る舞いとして適切かどうかはちょっとわかりません。

追記

「text プロパティでテキストを代入すると placeholder が消えない」というバグがあったので修正しておきました。

CocoaPods 対応

pod 'CSNPlaceholderTextView', '~> 0.0'