iOSアラートのテキストエリアで入力した内容をUIに反映させる

Swift4, iOS 12.1で作成

##つくるもの

　ボタンを押すとアラートが表示され、テキストエリアに入力するとLabelのテキストが入力されたものに変更されます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/93396/c04048d6-77a5-2820-0dad-590c3b630c98.png" width=40%><img src="https://qiita-image-store.s3.amazonaws.com/0/93396/cb6fb44d-c461-0383-29ce-d0bb91eb2a2c.png" width=40%>

##UI

　StoryBoardにLabelとButtonを配置します。ボタンに表示されるテキストを"alert"にしました。
<img src="https://qiita-image-store.s3.amazonaws.com/0/93396/c29aef88-2bff-32a2-1f57-3d262eb90b6b.png" width=40%>

　ViewControllerと連携させます。

![スクリーンショット 2019-01-13 16.38.16.png](https://qiita-image-store.s3.amazonaws.com/0/93396/cc6cf429-3c00-96d9-aba6-85d498624972.png)

##アラートを表示させる

　alertボタンが押された時にアラートを表示するようにコードを記述します。

```swift:ViewController
    @IBAction func myAlert(_ sender: Any) {
        let alertController = UIAlertController(title:"hoge", message:"fuga", preferredStyle: UIAlertController.Style.alert)
        
        present(alertController, animated:true, completion: nil)
    }
```

　アラートを表示するためにまずUIAlertControllerクラスのインスタンスを生成します。title:は太字のタイトル、message:はメッセージ、preferredStyle:はアラートスタイルです。
　今回はUIAlertController.Style.alertで中央に表示させるアラートを使用します。他にもアラートを下に表示させるUIAlertController.Style.actionsheetがあります。

　presentを使って上で生成したアラートを表示させます。animated:をtrueにするとアニメーション効果が付加されます。completion:はUIAlertControllerを表示したあとに実行するものですが、何もないのでnilにします。

　実行するとこのように表示されます：
<img src="https://qiita-image-store.s3.amazonaws.com/0/93396/dcb1feff-68b9-9b9e-bab9-62a28807225e.png" width=50%>

　このままだとこの表示から逃げられないのでOKボタンとCancelボタンを追加します。

##OK, Cancelボタンを追加

　インスタンスの生成alertControllerと、表示presentの間に以下のコードを挿入します。

```swift:ViewController
        let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default)
        alertController.addAction(okButton)
        
        let cancelButton = UIAlertAction(title: "cancel", style: UIAlertAction.Style.cancel, handler:nil)
        alertController.addAction(cancelButton)
```

　空行で分けた２つは殆ど同じ内容で、ボタンを定義しアクションを追加しています。

　UIAlertActionはアラート内でのアクションを定義します。title:はボタンに表示される内容、style:はスタイル、handlerはアクション後に実行する内容です。
　okButtonにはstyle:をUIAlertAction.Style.defaultで何らかの処理を行うボタンのスタイルを設定しています。
　一方cancelButtonはstyle:をUIAlertAction.Style.cancelとし、キャンセルボタンのアクションに設定しています。cancelにすると、何も変更されず操作をキャンセルするアクションとなります。
　cancelButtonにのみhandler:が設定されています。これはキャンセル後に実行する内容がないためnilにしています(現在のところokButtonも無いのですが、あとで追記します)。

　実行すると以下のようになります：
<img src="https://qiita-image-store.s3.amazonaws.com/0/93396/dab1f93d-b2c3-80b6-a167-1f38526d1233.png" width=40%>

　cancelボタンとOKボタンが追加されました。どちらをクリックしても元の画面に戻れることを確認してください。


##テキストエリアを追加

　アラート画面にテキストエリアを追加します。
　alertControllerと、okButtonの間にalertController.addTextFiledを追加してください。

```swift:ViewController
        let alertController = UIAlertController(title:"hoge", message:"fuga", preferredStyle: UIAlertController.Style.alert)
        
        alertController.addTextField()
        
        let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default)
        alertController.addAction(okButton)
```

　.addTextFiledでテキストエリアを追加できます。

　これを実行すると以下のようにテキストエリアが追加されます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/93396/19746325-55c5-4674-b3b1-618aff3734e6.png" width=40%>


##OKボタンでテキストを書き換える処理

　OKボタンにアクションを追加します。OKボタンをタップすると、テキストフィールドに書かれた文字列が、最初に用意したmyLabelに表示されるようにします。

　okButtonのUIAlertActionのインスタンス生成の部分を書き換えます。

```swift:ViewController
        let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default) { (action: UIAlertAction) in
            if let textField = alertController.textFields?.first {
                self.myLabel.text = textField.text
                }
        }
        alertController.addAction(okButton)
```

　UIAlertAction()をUIAlertAction(){}の形式に書き換え、OKボタンをタップした時に{}内の処理が行われるようにしています。

```swift:ViewController
            if let textField = alertController.textFields?.first {
                }
```

　alertControllerのtextFiledを参照します。alertControllerにtextFieldsがあるか無いかを調べるためにtextFileds?とオプショナル型になっています。ある場合に{}のコードが実行されます。.firstとなっているのはtextFieldsがArray型のためです。


```swift:ViewController
                self.myLabel.text = textField.text
```

　myLabelにtextFiledの文字列を入れます。クロージャ内なのでmyLabelには明示的にselfをつける必要があります。

##全コード

```swift:ViewController
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var myLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    
    @IBAction func myAlert(_ sender: Any) {
        let alertController = UIAlertController(title:"hoge", message:"fuga", preferredStyle: UIAlertController.Style.alert)
        
        alertController.addTextField()
        
        let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default) { (action: UIAlertAction) in
            if let textField = alertController.textFields?.first {
                self.myLabel.text = textField.text
                }
        }
        alertController.addAction(okButton)
        
        let cancelButton = UIAlertAction(title: "cancel", style: UIAlertAction.Style.cancel, handler:nil)
        alertController.addAction(cancelButton)
        
        present(alertController, animated:true, completion: nil)
    }
    
}
```


##完成
実行すると以下のように、OKボタンをタップするとテキストフィールドに入力した文字列で、Labelが置き換えられました。

<img src="https://qiita-image-store.s3.amazonaws.com/0/93396/c04048d6-77a5-2820-0dad-590c3b630c98.png" width=50%><img src="https://qiita-image-store.s3.amazonaws.com/0/93396/cb6fb44d-c461-0383-29ce-d0bb91eb2a2c.png" width=50%>