質問: 簡単なToDoリストを作ろうと思い、チェックボックスと、その横にあるTextfieldまでは作れました。 しかし、Textfieldで改行をしたら新しいチェックボックスが現れる(Evernoteのチェックボックス機能のようなものです)ようにしたいのですが、それができません。一体どうすればいいのでしょうか。
回答: *Delegateはなにかをお話しする前に、Delegateはなにに使われるか、どういう目的で使われるかという話をします。* ●イベント駆動型プログラム iOSは、種々のイベントを引き金(トリガー)にして、処理を開始する、イベント駆動型をとっています。ユーザが画面をタップする、キーボードで入力する、デバイス本体を傾けるという、ユーザが起こすイベント。アプリが、他のアプリの裏側に回ったとか、表に出てきたという、状態の変化を示すイベント。GPSから、位置情報の変更をイベントとすることもありますし、ネットワーク経由で、サーバの応答をイベントとして受け取ることもあります。(イベント駆動型プログラム) イベント発生から、処理を開始する仕組みは、いくつかの種類を、iOSは用意しています。 **Action-Targetパラダイム** XcodeのStoryboardで、ボタンを、ソースコード上のメソッドにConnect(接続)する作業を、なさったことがあると思います。画面操作のユーザイベントを受け取る`UIControl`オブジェクトがあり、指定された対象(Target)が持つメソッド(Action)を呼ぶ仕組みを、Action-Targetパラダイムといいます。 `UITextField`は、`UIControl`のサブクラスであり、ユーザのイベントを受け取るようになっています。Structure UIControlEventsに、`UIControl`が受け取るイベントの種類が一覧になっていますが、`editingDidBegin`や`editingDidEnd`のように、`UITextField`専用のイベントもあります。 **Notification(通知)** Action-Targetパラダイムは、基本1対1の関係でしたが、1対多でメソッドを呼び出す、Notificationというシステムがあります。詳しい説明はしませんが、使えるようになると、役立つシステムです。`UITextField`にも、`UITextFieldTextDidBeginEditing`、`UITextFieldTextDidChange`、`UITextFieldTextDidEndEditing`、3つのNotificationがあります。 ほかに、**Gesture Recognizer**がありますが割愛して、つぎにDelegateを取り上げます。 ●Delegate(委譲) ウィキペディアの委譲にあるように、Delegateは、イベント駆動専用で使われる手法ではありませんが、iOSではイベント駆動で呼び出すメソッドとして、多用されます。XcodeでiOSのプロジェクトを作成すると、かならず`AppDelegate`クラスができますが、これは`UIApplication`のDelegateを集めたクラスになっています。 UIKitのリファレンス上では、Delegateはプロトコルにまとめられていますから、`UITextField`のDelegateは、`UITextFieldDelegate`で調べることができます。じっさいに調べてみると、`textFieldShouldReturn(_:)`というDelegateメソッドがあり、その名からテキストフィールド入力中に、リターンキーをタップした時に、呼ばれるメソッドではないかと想像されます。そして、そのとおり呼ばれます。 ●Delegateメソッドの実装 Delegateメソッドの具体的な実装の仕方を説明します。 まず、委譲元にしたいオブジェクト(クラス)が、本当に委譲できるのか確認します。確認の仕方はかんたんで、クラスリファレンスを調べ、`delegate`プロパティがあれば、委譲ができます。`UITextField`クラスにも`delegate`プロパティがあるので、委譲できます。 委譲先のオブジェクトを指定します。さきの`delegate`プロパティに、委譲先のオブジェクトを代入します。 ``` class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() textField.delegate = self // View Controller自身を、委譲先とする。 } } ``` この記述は、Storyboard上の編集としても行えます。Text FieldからView Controllerに接続して、表示されたプルダウンメニューから選択します。 !画像の説明をここに入力 つぎに、委譲先オブジェクトに、Delegateメソッドを定義します。 クラス宣言に、プロトコル名`UITextFieldDelegate`を追加します。 ``` class ViewController: UIViewController, UITextFieldDelegate { ``` 忘れやすいので、気をつけてください。 Delegateメソッドには、Required(必須)と、Optional(オプション)の2種類があり、Requiredは、その名のとおり、かならず実装しなければいけません。`UITextFieldDelegate`のメソッドは、すべてOptionalで、実装したいものだけ定義します。詳しくは、各Delegateプロトコルのリファレンスに書かれていますから、使用時、熟読することをお勧めします。 ``` func textFieldShouldReturn(_ textField: UITextField) -> Bool { print("Return key was pressed.") textField.resignFirstResponder() return true } ``` iOSシミュレータで実行してみて、Text Fieldにテキスト入力後、リターンキーを押して、上のメソッドが実行されることを、確認してください。ちなみに、`resignFirstResponder()`メソッドは、キーボードを非表示にする役目があります。そして、`textFieldShouldReturn(_:)`メソッドは、`Bool`型の返り値を持っていることに注意してください。`true`を返さないと、リターンキーのプレスがキャンセルになります。 ●まとめ 1. Delegateは、イベント発生を受けて、メソッドを実行する手法として、使われることが多い。 2. Delegateメソッドは、プロトコルとしてまとめられている。 3. Delegateメソッドには、RequiredとOptionalがある。