Apple公式のiPhoneアプリチュートリアルやってみた②(Connect the UI to Code)

#Connect the UI to Source Code
[Apple公式のiPhoneアプリチュートリアルやってみた①(Build a Basic UI)](http://qiita.com/naogify/items/693c14d56803b49ff85f)の続きです。

今回はタイトルのままstorybooard上のUIとコードをつなげていきます。


######UIとソースコードを繋げる
ストーリボード上の要素と、ソースコードは繋げることができます。ストリーボード上におけるscene とは、大抵View controllersのことを指します。View controllersは、そのアプリの挙動を実行します。そしてView controllersはデータに関することを管理し、画面が横むきになった時の情報や、ユーザーのインプット情報に対してどう反応するのかを決めています。（iOSの中でのView controllersのオブジェクトは、UIViewControllerという型です。）

私たちは、UIViewControllerの挙動を、　view controllerのsubclassesのコードを書くことで決定できます。そしてそのsubclassesとStory Board上の要素（scene）を繋ぐことができます。


Story Board上の要素（scene）とソースコードを繋ぐには、 Identity inspectorを使います。

<img width="272" alt="CUIC_inspector_identity_2x.png" src="https://qiita-image-store.s3.amazonaws.com/0/142797/a7d93990-85ff-4769-d8db-feda52afc6ca.png">


今Xcodeの中では、storyboardの要素（scene）の挙動は、ViewController.swiftの中のソースコードによって定義されています。

しかし他にも、"outlets" と "actions"という繋ぎ方があります。



######「Outlets」で、ソースコードと要素を繋げる

Outlets接続は、ソースコードからStoryBoard上の要素を参照して、修正や、値をにを取得するためにあります。（例：テキストフィールドや、テキストフィールドの持つ値）

######テキストフィールドのOutlets接続
　　1.Main.storyboardを開く。
　　2. Assistant editorを開く。
<img width="307" alt="assistant_editor_toggle_2x.png" src="https://qiita-image-store.s3.amazonaws.com/0/142797/7c055b87-ef99-a7d4-a6b5-c0e5abda2364.png">

　　3. もし必要なら、 project navigatorとutility areaを左右に閉じる。
　　4. 下のように、assistant editorから、Automatic > ViewController.swiftを選択する。
<img width="680" alt="CUIC_switchtoviewcontroller_2x.png" src="https://qiita-image-store.s3.amazonaws.com/0/142797/da84de53-997d-d019-fc04-3c052b2daf7a.png">

　　ViewController.swiftが右に表示される。

　　5.ViewController.swiftの中から下の一行を見つける。
　　`class ViewController: UIViewController {`

　　6.見つけた行のすぐ下に、この一行を追加。
　　`//MARK: Properties`（コメントで、プロパティと書いている。）

　　7.StoryBoard上でテキストフィールドを選択する。
　　8."Controlボタン"を押しながら、今追加したコメントのすぐ下にドラッグアンドドロップする。

<img width="680" alt="CUIC_textfield_dragoutlet_2x.png" src="https://qiita-image-store.s3.amazonaws.com/0/142797/6e5ac289-61f5-51d0-0632-5154a8041b6d.png">

　　9.ポップアップが表示されたら、NameのところにnameTextFieldと入力。他はそのままでおいておく。

<img width="680" alt="CUIC_textfield_addoutlet_2x.png" src="https://qiita-image-store.s3.amazonaws.com/0/142797/bdb44f41-0d95-ba1b-f316-34f040c4b44a.png">

　　10. Connectをクリックする。
　　すると以下のコードがViewController.swiftに追加される。
　　`@IBOutlet weak var nameTextField: UITextField!`
  
 コードを解説すると、
　　　　・IBOutlet：nameTextFieldプロパティにInterface Builderから接続できるというコトをXcodeに伝えている。（Interface Builderの略でIBとついている。） 

　　　　・weak：システムの予約後に上書きしない。

　　　　・var nameTextField: UITextField!：UITextFieldという型の指定した要素に、nameTextFieldという変数名をつける。
　　　　　　

######ラベルのOutlets接続

 1.同じようにストリーボード上でラベルを選択。
　　2.Control + ドラッグアンドドロップで、さっき追加したnameTextFieldすぐ下に追加。
 <img width="680" alt="CUIC_label_dragoutlet_2x.png" src="https://qiita-image-store.s3.amazonaws.com/0/142797/9af21a1d-a002-43fb-f1ca-fc9e24c7d9d0.png">

　　3.ボップアップが開くとNameにmealNameLabelと入力。

 <img width="680" alt="CUIC_label_addoutlet_2x.png" src="https://qiita-image-store.s3.amazonaws.com/0/142797/43d86947-2f1b-a62c-3761-96e838bb4f3e.png">
 4. Connectを押すと、下の一行が追加される。
 `@IBOutlet weak var mealNameLabel: UILabel!`(要素の型は、Storyboard上の要素と合わせて、UILabel)
これで要素の参照はできるようになりました。次はユーザーの入力に合わせて挙動する要素の為に、actionを勉強しましょう。


######Action接続
action（action method）は、アプリ内でおこるイベントに関連しているコードです。何かイベントが起こると、ViewController.swift内にあるactionに関連しているコードを実行します。actionはoutletと基本同じように作ります。

  1.ViewController.swiftファイルの中の一番最後の"}"の上に、下のコードを追加します。
  `//MARK: Actions`(これはアクションの記述をしますというコメント)

  2.StoryBoard上で、"Set Default Label Text"ボタンを選択します。

  3.Control + ドラッグアンドドロップで、さっき追加した`//MARK: Actions`のすぐ下に追加。

  4.ボップアップが開くと、ConnectionでActionを選択、NameにsetDefaultLabelTextと入力。TypeにはUIButtonを選択。

  5. Connectを選択。
  すると、Xcodeは、
`@IBAction func setDefaultLabelText(_ sender: UIButton) {
}`
を追加する。

  ・senderパラメーターはこのActionが、どのオブジェクトに関連づけられているかを示します。（この例では　button）
  ・ IBActionは、InterfaceBuilderから関連づけられたActionということを示し。
　　　　・残りは、空のsetDefaultLabelText(_:)というメソッド（関数)を指定しています。

  6. setDefaultLabelText(_:){}の、"{}"の中に、下の一行を追加します。
  `mealNameLabel.text = "Default Text"`
  これは、ラベルのtextプロパティに、Default Textを設定しています。
　　　　そして、Default Textのデータの型を指定していないことに気づいた方もいるかもしれませんが、Swiftでは、自動で推測してくれるそうです。

  完成形はこれです。
  `@IBAction func setDefaultLabelText(_ sender: UIButton) {
    　　　　mealNameLabel.text = "Default Text"
　 }`


######ユーザーの入力を処理する
次はユーザーがテキストフィールドを使用して自分の食事名を入力できるようにします。つまり、ユーザーがテキストフィールドにテキストを入力してReturnキーを押すたびに、mealNameLabelオブジェクトのテキスト値を更新します。
テキストフィールドからのユーザー入力を受け入れる場合は、text field delegateを使う必要があります。デリゲートは、別のオブジェクトの代わりに、または別のオブジェクトと連携して動作するオブジェクトです。

テキストフィールドのdelegateは、ユーザーがテキストを編集している間にテキストフィールドと通信し、ユーザーがテキストの編集を開始または停止するときなど、重要なイベントがいつ発生するかを知っています。デリゲートは、この情報を使用して、適切なタイミングでデータを保存またはクリアしたり、キーボードを閉じたりすることができます。
(正直delegateはまだ理解していないです><)


  1.アシスタントエディタが開いている場合は、下のボタンをクリックしてStandard editorに戻ります。

<img width="372" alt="standard_toggle_2x.png" src="https://qiita-image-store.s3.amazonaws.com/0/142797/c5cb7895-5038-1f4c-e268-6a3080ae4598.png">

  2.プロジェクトナビゲータで、ViewController.swiftを選択します。
  3.ViewController.swiftの中で、下のようなクラスを見つけます。
  `class ViewController: UIViewController {`
  4.UIViewControllerの後に、コンマ（、）とUITextFieldDelegateを追加します。
  `class ViewController: UIViewController, UITextFieldDelegate {`
  このプロトコルの追加により、ViewControllerは、テキストフィールドdelegateの機能をもつようになります。

######ViewControllerオブジェクトをnameTextFieldプロパティのデリゲートとして設定する。

  1.ViewController.swiftの中で、下の様なviewDidLoad（）メソッドを探します。
  `override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
  }`
  このメソッドのテンプレート実装にはコメントが含まれています。メソッド実装でこのコメントは必要ないので、先に進んで削除してください。

  2.super.viewDidLoad（）行の下に、空白行と次の行を追加します。
  `// Handle the text field’s user input through delegate callbacks.
nameTextField.delegate = self`

  (selfは、ViewControllerクラスを参照します、それはViewControllerクラスのスコープ内に上のコードが書かれている為です。)

  viewDidLoad（）メソッドは次のようになります。
`override func viewDidLoad（）{
    super.viewDidLoad（）
    
    // Handle the text field’s user input through delegate callbacks.
    nameTextField.delegate = self
}`


UITextFieldDelegateを定義するのには8つのオプションがあります。しかし今使うのは下の二つのみです。

`func textFieldShouldReturn(_ textField: UITextField) -> Bool
func textFieldDidEndEditing(_ textField: UITextField)`


このメソッドがいつ呼ばれて、何をするかを理解するのにはテキストフィールドがどのようにユーザのイベントに反応するかを知る必要があります。ユーザーがテキストフィールドをタップした時、それは自動的にfirst responderになります。first responderオブジェクトは、key、モーション、action messagesなど様々なアプリのイベントを最初に受け取るものになります。テキストフィールドがfirst responderになった結果としてiOSはキーボードを表示し、文字の入力セッションが開始されます、キーボードで入力した文字はテキストフィールドに挿入されます。

これが、UITextFieldDelegateメソッドが役に立つ時です。そしてあなたは、ユーザーが文字入力終了のボタンを押した時、first-responderのステータスが終了するように設定しなければなりません。



######textFieldShouldReturn(_:)を実装する。

  1.ViewController.swiftの中の//MARK: Actionsのすぐ上に以下を付け足す。 
`//MARK: UITextFieldDelegate`

  2.そのコメントのすぐ下に、以下のメソッドを付け足す。
`func textFieldShouldReturn(_ textField: UITextField) -> Bool {
}`

  3.付け足したメソッドの中に、textFieldのresignFirstResponderを終了させる為に、以下のコードを付け足す。
`// Hide the keyboard.
 textField.resignFirstResponder()
 return true
`
完成形は以下、
`
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    // Hide the keyboard.
    textField.resignFirstResponder()
    return true
}
`


######textFieldDidEndEditing(_:)を実装する。

  1.ViewController.swiftの中の、textFieldShouldReturn(_:)のすぐ後に、以下のメソッドを加える。
`
func textFieldDidEndEditing(_ textField: UITextField) {
}
`

  2.そのメソッドの中に以下の行を加える。
`mealNameLabel.text = textField.text`

完成形
`
func textFieldDidEndEditing(_ textField: UITextField) {
    mealNameLabel.text = textField.text
}
`

ここでiOSシミュレーターを立ち上げ、テキストフィールドで文字を入力した後、"完了"ボタンを押す。キーボードが消え、ラベルが入力した文字に変わるか、”Set Default Label Text button”を押すと"Default Text"に文字が変わるかを確認します。
<img width="387" alt="CUIC_sim_finalUI_2x.png" src="https://qiita-image-store.s3.amazonaws.com/0/142797/5a041ed3-f473-95f2-6cd8-66265e6135f2.png">


Apple公式のiPhoneアプリチュートリアルやってみた③(Work with View Controllers)に続きます。