[iOS] UITextFieldやUITextViewで入力できる文字列を制限する

2016.06.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは!加藤 潤です。
今回はUITextFieldUITextView で入力できる文字列を制限する方法をご紹介します。

開発環境

  • Xcode 7.3.1 (7D1014)
  • iPhone 6s シミュレータ / iOS 9.3 (13E230)
  • Swift 2.2

こんなケースありませんか?

iOSアプリ開発でユーザーに任意のテキストを入力させる場合、UITextFieldUITextViewを使うと思いますが、その際以下のように「入力できる文字列を制限したい」というニーズは多いと思います。

  • 半角数字だけ入力させたい
  • 半角英数字だけ入力させたい
  • メールアドレスで使用可能な文字だけ入力させたい
  • etc...

例えば、キーボードタイプをUIKeyboardType.NumberPadに設定することで半角数字だけ入力させることが可能ですが、キーボードから入力する場合はそれで良いのですが、メモアプリなどからコピー&ペーストで入力できてしまうためこれだけでは実は不十分だったりします。 そこで今回は他のアプリからコピー&ペーストされても指定した条件を満たさないテキストは入力できないように制限したいと思います。

半角数字だけ入力できるようにする

例としてここでは「半角数字だけ入力できるようにする」方法をご紹介します。 まずはそのための正規表現を考えましょう。 こんな感じになると思います。 ^[0-9]+$(0から9が1文字以上)

UITextFieldで入力を制限する

UITextFieldで入力を制限するにはUITextFieldDelegateの下記関数を実装します。

@available(iOS 2.0, *)
optional public func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool // return NO to not change text

この関数はUITextFieldのテキストに入力がある度に呼ばれます。 引数のtextFieldに対象のUITextField、rangeに置換される文字列の範囲、stringに置換する文字列が渡ってきます。 このメソッドでtrueを返せばテキストは変化し、falseを返せばテキストは変化せずに以前のテキストが保持されます。

つまり、このメソッド内でstringの文字列を正規表現でチェックし、指定したパターンに当てはまる場合だけtrueを返してあげれば良いということになります。 下記は実装例です。

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    return string.isEmpty || string.rangeOfString("^[0-9]+$", options: .RegularExpressionSearch, range: nil, locale: nil) != nil
}

正規表現チェックには下記関数を使用し、オプションには.RegularExpressionSearchを指定します。

@warn_unused_result
public func rangeOfString(aString: String, options mask: NSStringCompareOptions = default, range searchRange: Range<Index>? = default, locale: NSLocale? = default) -> Range<Index>?

実装のポイントは下記の2点です。

  • ユーザーがDeleteキーで文字を削除した場合はstringが空となるのでstring.isEmptyを満たす場合もtrueを返すようにする
  • rangeOfStringはマッチしなかった場合はnilが返るので、nilではない場合にtrueを返すようにする

UITextViewで入力を制限する

UITextViewで入力を制限するにはUITextViewDelegateの下記関数を実装します。

@available(iOS 2.0, *)
optional public func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool

この関数もUITextViewのテキストに入力がある度に呼ばれます。 UITextFieldの時と同じように実装すればOKです。

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    return text.isEmpty || text.rangeOfString("^[0-9]+$", options: .RegularExpressionSearch, range: nil, locale: nil) != nil
}

まとめ

今回はUITextField や UITextView で入力できる文字列を制限する方法をご紹介しました。
正規表現の部分を差し替えることで様々な入力要件に対応できるかと思います。

参考