32703


簡単なToDoリストを作ろうと思い、チェックボックスと、その横にあるTextfieldまでは作れました。  
しかし、Textfieldで改行をしたら新しいチェックボックスが現れる（Evernoteのチェックボックス機能のようなものです）ようにしたいのですが、それができません。一体どうすればいいのでしょうか。


CC BY-SA 3.0
2017-02-15T13:36:47.187
32690
2017-03-18T09:11:19.000
2017-02-15T14:35:59.363
76
20671
question
swift
リターンキーを押すと新しい行にチェックボックスを生成する


_Delegateはなにかをお話しする前に、Delegateはなにに使われるか、どういう目的で使われるかという話をします。_

●イベント駆動型プログラム

iOSは、種々のイベントを引き金（トリガー）にして、処理を開始する、イベント駆動型をとっています。ユーザが画面をタップする、キーボードで入力する、デバイス本体を傾けるという、ユーザが起こすイベント。アプリが、他のアプリの裏側に回ったとか、表に出てきたという、状態の変化を示すイベント。GPSから、位置情報の変更をイベントとすることもありますし、ネットワーク経由で、サーバの応答をイベントとして受け取ることもあります。[（イベント駆動型プログラム）](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E9%A7%86%E5%8B%95%E5%9E%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)  
イベント発生から、処理を開始する仕組みは、いくつかの種類を、iOSは用意しています。  
**Action-Targetパラダイム**  
XcodeのStoryboardで、ボタンを、ソースコード上のメソッドにConnect（接続）する作業を、なさったことがあると思います。画面操作のユーザイベントを受け取る`UIControl`オブジェクトがあり、指定された対象（Target）が持つメソッド（Action）を呼ぶ仕組みを、Action-
Targetパラダイムといいます。  
`UITextField`は、`UIControl`のサブクラスであり、ユーザのイベントを受け取るようになっています。[Structure
UIControlEvents](https://developer.apple.com/reference/uikit/uicontrolevents)に、`UIControl`が受け取るイベントの種類が一覧になっていますが、`editingDidBegin`や`editingDidEnd`のように、`UITextField`専用のイベントもあります。  
**Notification（通知）**  
Action-
Targetパラダイムは、基本1対1の関係でしたが、1対多でメソッドを呼び出す、Notificationというシステムがあります。詳しい説明はしませんが、使えるようになると、役立つシステムです。`UITextField`にも、[`UITextFieldTextDidBeginEditing`](https://developer.apple.com/reference/foundation/nsnotification.name/1619616-uitextfieldtextdidbeginediting)、[`UITextFieldTextDidChange`](https://developer.apple.com/reference/foundation/nsnotification.name/1619640-uitextfieldtextdidchange)、[`UITextFieldTextDidEndEditing`](https://developer.apple.com/reference/foundation/nsnotification.name/1619633-uitextfieldtextdidendediting)、3つのNotificationがあります。  
ほかに、 **Gesture Recognizer** がありますが割愛して、つぎにDelegateを取り上げます。

* * *

●Delegate（委譲）

ウィキペディアの[委譲](https://ja.wikipedia.org/wiki/%E5%A7%94%E8%AD%B2)にあるように、Delegateは、イベント駆動専用で使われる手法ではありませんが、iOSではイベント駆動で呼び出すメソッドとして、多用されます。XcodeでiOSのプロジェクトを作成すると、かならず`AppDelegate`クラスができますが、これは`UIApplication`のDelegateを集めたクラスになっています。  
UIKitのリファレンス上では、Delegateはプロトコルにまとめられていますから、`UITextField`のDelegateは、[`UITextFieldDelegate`](https://developer.apple.com/reference/uikit/uitextfielddelegate)で調べることができます。じっさいに調べてみると、`textFieldShouldReturn(_:)`というDelegateメソッドがあり、その名からテキストフィールド入力中に、リターンキーをタップした時に、呼ばれるメソッドではないかと想像されます。そして、そのとおり呼ばれます。

* * *

●Delegateメソッドの実装

Delegateメソッドの具体的な実装の仕方を説明します。  
まず、委譲元にしたいオブジェクト（クラス）が、本当に委譲できるのか確認します。確認の仕方はかんたんで、クラスリファレンスを調べ、`delegate`プロパティがあれば、委譲ができます。`UITextField`クラスにも[`delegate`](https://developer.apple.com/reference/uikit/uitextfield/1619595-delegate)プロパティがあるので、委譲できます。  
委譲先のオブジェクトを指定します。さきの`delegate`プロパティに、委譲先のオブジェクトを代入します。

[code]

    class ViewController: UIViewController {
    
        @IBOutlet weak var textField: UITextField!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            textField.delegate = self // View Controller自身を、委譲先とする。
        }
    
    }
    
[/code]

この記述は、Storyboard上の編集としても行えます。Text FieldからView
Controllerに接続して、表示されたプルダウンメニューから選択します。

[![画像の説明をここに入力](https://i.stack.imgur.com/m9slG.png)](https://i.stack.imgur.com/m9slG.png)

つぎに、委譲先オブジェクトに、Delegateメソッドを定義します。  
クラス宣言に、プロトコル名`UITextFieldDelegate`を追加します。

[code]

    class ViewController: UIViewController, UITextFieldDelegate {
    
[/code]

忘れやすいので、気をつけてください。  
Delegateメソッドには、Required（必須）と、Optional（オプション）の2種類があり、Requiredは、その名のとおり、かならず実装しなければいけません。`UITextFieldDelegate`のメソッドは、すべてOptionalで、実装したいものだけ定義します。詳しくは、各Delegateプロトコルのリファレンスに書かれていますから、使用時、熟読することをお勧めします。

[code]

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        print("Return key was pressed.")
        textField.resignFirstResponder()
    
        return true
    }
    
[/code]

iOSシミュレータで実行してみて、Text
Fieldにテキスト入力後、リターンキーを押して、上のメソッドが実行されることを、確認してください。ちなみに、`resignFirstResponder()`メソッドは、キーボードを非表示にする役目があります。そして、`textFieldShouldReturn(_:)`メソッドは、`Bool`型の返り値を持っていることに注意してください。`true`を返さないと、リターンキーのプレスがキャンセルになります。

* * *

●まとめ

  1. Delegateは、イベント発生を受けて、メソッドを実行する手法として、使われることが多い。
  2. Delegateメソッドは、プロトコルとしてまとめられている。
  3. Delegateメソッドには、RequiredとOptionalがある。


CC BY-SA 3.0
2017-02-16T03:27:26.733
32703
2017-02-16T03:27:26.733
18540
32690
answer