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

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

###やること
---
#####1.StorybordにTextFieldを設置する
#####2.キーボードを閉じる動作をつける
#####3.入力文字制限をつける
という流れになります。



####1.StorybordにTextFieldを設置する
---
まずはStorybord常にTextFieldを設置します。
![スクリーンショット 2021-06-06 3.57.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683204/53b2ef83-8a13-47ac-eb22-f4023b109903.png)
右上の「+」ボタンを押し
![スクリーンショット 2021-06-06 3.58.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683204/83d0d0e9-f95a-0d13-1794-d61cd4847e96.png)
「TextField」を選択します。
![スクリーンショット 2021-06-06 4.00.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683204/a693eeaf-7381-f9f0-79e3-92a5c597b5fc.png)
ちょっと見づらいですが、中央にTextFieldを設置することができました。
これでビルドしてみます。
![スクリーンショット 2021-06-06 5.34.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683204/30398906-7d19-1f7a-e00e-53cc52de8bc4.png)

先ほど設置したTextFieldをタップするとキーボードが表示されます。
もし表示されなければ
[I/O]->[Keyboard]->[Toggle Software Keyboard]を選択し、再度TextFieldをタップすることでキーボードがでます。
![スクリーンショット 2021-06-06 4.07.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683204/d7219c3e-feb4-c4d4-6041-719606c9a0aa.png)


####2.キーボードを閉じる動作をつける
---
TextFieldの設置ができました。
しかし、キーボードを閉じることができません・・・。
右下の「改行」や「return」をタップしても、キーボード外をタップしても閉じることができません。
閉じる処理をつけなければいけません。
Storybord上のTextFiledで右クリックをし[Did End On Exit]をViewControllerへcontrolキー + ドラッグします。
これで「改行」「return」で閉じることができます。
![スクリーンショット 2021-06-06 4.32.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683204/d9e5c1f6-7549-10a4-486a-0112721ca1e0.png)

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

```swift: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に文字制限をつけてみます。
指定した文字数以上は入力できないようにします。

```swift
@objc func maxLength(textField: UITextField) {
        guard let text = textField.text else { return }
        let length = 10
        textField.text = String(text.prefix(length))
}
```
lengthで文字数を決めます。

```swift
textField.text = String(text.prefix(length))
```
でTextFiled内の最大文字数をlengthにします。
このメソッドをaddTargetで適用させます。

```swift
textField.addTarget(self, action: #selector(maxLength(textField:)), for: .editingChanged)
```
これで文字数制限をつけることができました。

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

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

```swift
if textField.markedTextRange != nil {
        return
}
```
をmaxLengthメソッド内に入れてあげて文字入力中はメソッドの処理を行わないようにしてあげます。

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


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

```swift
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))
    }
}
```

以上です。