【swift】textfieldを設置し文字数制限をつける


自身で実装した内容をまとめていきます。
指定の箇所をタップしたとき、キーボードを表示し、文字制限をつける処理を行う。

やること


1.StorybordにTextFieldを設置する
2.キーボードを閉じる動作をつける
3.入力文字制限をつける

という流れになります。

1.StorybordにTextFieldを設置する


まずはStorybord常にTextFieldを設置します。

右上の「+」ボタンを押し

「TextField」を選択します。

ちょっと見づらいですが、中央にTextFieldを設置することができました。
これでビルドしてみます。

先ほど設置したTextFieldをタップするとキーボードが表示されます。
もし表示されなければ
[I/O]->[Keyboard]->[Toggle Software Keyboard]を選択し、再度TextFieldをタップすることでキーボードがでます。

2.キーボードを閉じる動作をつける


TextFieldの設置ができました。
しかし、キーボードを閉じることができません・・・。
右下の「改行」や「return」をタップしても、キーボード外をタップしても閉じることができません。
閉じる処理をつけなければいけません。
Storybord上のTextFiledで右クリックをし[Did End On Exit]をViewControllerへcontrolキー + ドラッグします。
これで「改行」「return」で閉じることができます。

次にTextField外すなわちキーボード外をタップしたときにキーボードを閉じる処理を加えます。
Storybord上のTextFiledをViewControllerにcontrolキー + ドラッグし、IBOutletを作成します。
「touchesBegan」メソッドをオーバーライドします。
そしてendEditingという処理を入れてあげることでキーボード外をタップしたときに閉じることができます。

ViewController.swift
class ViewController: UIViewController {

    //Storybordからcontrolキー + ドラッグ
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    //ここでtouchesBeganをオーバーライド
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            //閉じるための処理を記述します。
            self.view.endEditing(true)
    }
}

これでキーボード外をタップしたときも閉じるようになります。

3.入力文字制限をつける


TextFieldに文字制限をつけてみます。
指定した文字数以上は入力できないようにします。

@objc func maxLength(textField: UITextField) {
        guard let text = textField.text else { return }
        let length = 10
        textField.text = String(text.prefix(length))
}

lengthで文字数を決めます。

textField.text = String(text.prefix(length))

でTextFiled内の最大文字数をlengthにします。
このメソッドをaddTargetで適用させます。

textField.addTarget(self, action: #selector(maxLength(textField:)), for: .editingChanged)

これで文字数制限をつけることができました。

しかし、この状態では日本語の変換や濁点などをつけることができません

1文字入力されるたびに先ほど作成したmaxLengthメソッドの処理を行なってしまっています。文字が入力されるたびに確定されてしまうためですね。
これを避けるには

if textField.markedTextRange != nil {
        return
}

をmaxLengthメソッド内に入れてあげて文字入力中はメソッドの処理を行わないようにしてあげます。

これで問題なく変換や濁点をつけることができます。

最終的に以下になります。

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        textField.addTarget(self, action: #selector(maxLength(textField:)), for: .editingChanged)
    }

    @IBAction func textFieldClose(_ sender: Any) {
    }
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            self.view.endEditing(true)
    }
    @objc func maxLength(textField: UITextField) {
        if textField.markedTextRange != nil {
            return
        }
        guard let text = textField.text else { return }
        let length = 10
        textField.text = String(text.prefix(length))
    }
}

以上です。