【Swift】UITableViewControllerを使って、チャットアプリにトークルームを追加する

# はじめに
## この記事で学べること
- UITableViewControllerの簡単な使い方
- NavigationControllrの簡単な使い方

# 1. NavigationControllerの追加
新しいUIを追加する。
`Navigation Controller`を検索して、ドラッグ&ドロップで追加する

<img width="994" alt="Screen Shot 2019-07-03 at 5.01.07 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/6c98b077-0cf5-c44a-7251-d9b4e904c63c.png">

# 2. セグエを変更して、画面遷移の流れを変更する
下記の図のようにドラッグ&ドロップして、結びつけを変更します。

<img width="517" alt="Screen Shot 2019-07-03 at 5.07.13 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/fd81544e-bc0a-e4a3-febd-7f1e77d7f5c3.png">

Entry Pointのセグエを変更して、起動時の初期画面を変更します。

<img width="614" alt="Screen Shot 2019-07-03 at 5.07.32 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/6ad69f82-ca80-09d2-6570-029f37ba96ee.png">

# 3. 新しい画面用のSwiftファイルを作成する。

<img width="422" alt="Screen Shot 2019-07-03 at 5.34.29 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/bd17e1fe-7db5-a53d-1ce3-bbfec826662d.png">

<img width="745" alt="Screen Shot 2019-07-03 at 5.34.43 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/5eeb2be7-e00d-4abc-837e-8bb89426394c.png">

<img width="745" alt="Screen Shot 2019-07-03 at 5.34.43 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/e5aa5e6a-e0e7-8576-2cd9-0555ed2c1ed2.png">

<img width="850" alt="Screen Shot 2019-07-03 at 5.35.15 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/aa6166f6-da3a-5a98-2e7b-989640fa30b3.png">

`TalkRoomViewController`クラスを作成する。

```Swift:TalkRoomViewController.swift

import Foundation
import UIKit

class TalkRoomViewController: UITableViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
}
```

# 4. StoryboardのViewControllerとクラスを紐付ける

<img width="688" alt="Screen Shot 2019-07-03 at 5.44.20 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/e40ff689-8311-a922-caf6-ef86e3c45958.png">

# 5. Cellの作成をする。
Cellの数を指定する。


``` Swift:TalkRoomViewController.swift

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

```

Cellを作成し、タイトルを設定する。

```Swift:TalkRoomViewController.swift

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        cell.textLabel?.text = "Room1"
        return cell
    }

```

# 6. Cell選択時に画面遷移する処理の追加

SegueのIDを設定

<img width="674" alt="Screen Shot 2019-07-03 at 5.54.17 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/3797d6f5-3f6d-f05e-f7c1-9d1e1116349c.png">


Cell選択時の処理を追加

```Swift:TalkRoomViewController.swift

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.performSegue(withIdentifier: "showRoomView", sender: nil)
    }

```

# 7. トークルームの新規作成画面を追加する

`Main.storyboard`ファイルを開き、新しい`UIViewController`を追加します。

<img width="1015" alt="Screen Shot 2019-07-04 at 11.24.47 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/d658d0b6-1234-4495-a813-3ef040c1804b.png">

新規作成したUIViewControllerに以下の3つを追加する。

- UILabel
- UITextField
- UIButton

<img width="955" alt="Screen Shot 2019-07-04 at 11.30.03 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/99b4efff-d013-a987-5453-f59ee3a619e6.png">

StackViewを使用して、レイアウトを調整します。

追加した3つのUI部品を選択して、赤枠の箇所を選択します。

<img width="471" alt="Screen Shot 2019-07-04 at 11.30.17 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/5df9c951-c913-b75d-f005-d2a097f66ffb.png">

`Stack View`を選択します。

<img width="577" alt="Screen Shot 2019-07-04 at 11.30.32 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/74660508-52e4-31ee-e6df-c49411447ac8.png">

StackViewの位置を指定します。

StackViewを画面中央に指定します。

<img width="1022" alt="Screen Shot 2019-07-04 at 11.31.22 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/3f2089f9-a3f1-b199-34af-41b23b52070b.png">

左右の余白の指定をします。

<img width="1046" alt="Screen Shot 2019-07-04 at 11.31.38 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/4c86b6c3-fe99-1467-9d57-77050eb863b2.png">

StackView内のUIの配置方法を指定します。
Aligment: StackView内の要素の揃え位置を指定
Disribution: StackView内の要素の配置方法を指定

<img width="1158" alt="Screen Shot 2019-07-04 at 1.19.19 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/55b724f2-bfbb-481e-d1c7-e0fae5f4f7b2.png">

# 8. 新しい画面のクラスを作成します。

下記画面のように対象ディレクトリを選択して、`New File...`を選択します。

<img width="358" alt="Screen Shot 2019-07-04 at 11.47.04 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/417a471e-6690-b399-f5ee-c9540b41063d.png">

<img width="735" alt="Screen Shot 2019-07-04 at 11.47.23 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/bda16e5b-53dd-d6b2-dc44-7a28e7cd01ec.png">

`CreateTalkRoomViewController.swift`ファイルを新規作成します。

<img width="843" alt="Screen Shot 2019-07-04 at 11.47.42 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/29cbd4ed-5b61-62f0-983b-6cae6baa8cac.png">

```Swift:CreateTalkRoomViewController.swift

import Foundation
import UIKit

class CreateTalkRoomViewController:  UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

```

UIとコードを接続します。

<img width="703" alt="Screen Shot 2019-07-04 at 1.45.20 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/bdfd9c14-c2c5-8d52-c45a-3fcda0f49cd4.png">


# 9. 新規トークルーム追加用のCellを追加

セルの数を変更

```Swift:TalkRoomViewController.swift

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 2
    }

```

新規トークルーム追加用のセルを作成

```Swift:TalkRoomViewController.swift

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        switch  indexPath.row {
        case 0:
            cell.textLabel?.text = "Room1"
        default:
            cell.textLabel?.text = "+ Create New Room"
            cell.textLabel?.textColor = UIColor.blue
        }
        return cell
    }

```

# 10. Cellタップ時の画面遷移処理を追加

Segue のIDを指定。

<img width="856" alt="Screen Shot 2019-07-04 at 1.54.15 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/e30d651c-31a7-5140-af8c-849573be6925.png">


```Swift:TalkRoomViewController.swift

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        switch indexPath.row {
        case 0:
            self.performSegue(withIdentifier: "showRoomView", sender: nil)
        default:
            self.performSegue(withIdentifier: "modalCreateRoomView", sender: nil)
            return
        }
    }

```

# 11. Createボタン押下時にFirebaseにデータを保存する処理の追加

CreateTalkRoomViewControllerから戻る処理を追加

```Swift:CreateTalkRoomViewController.swift

    @IBAction func tappedCreateButton(_ sender: Any) {
        self.dismiss(animated: true, completion: nil)
    }

```

Createボタン押下時にFirebaseにデータを保存する処理の追加

```Swift:CreateTalkRoomViewController.swift

    @IBAction func tappedCreateButton(_ sender: Any) {
        
        if let roomName = inputRoomView.text, !roomName.isEmpty {
            let instanceValue = ["name":"name", "message":"message"]
            databaseRef.child(roomName).childByAutoId().setValue(instanceValue)
        }
        
        self.dismiss(animated: true, completion: nil)
    }

```

# 12. トークルームの読み込み処理を追加

ライブラリをimportする。

```Swift:TalkRoomViewController.swift

import  FirebaseDatabase

```

データベースを初期化する
データベースの変数を宣言して、インスタンスを生成する。
且つ、テーブルに表示するデータを変数として宣言する。

```Swift:TalkRoomViewController.swift

    var databaseRef: DatabaseReference!

    var roomData = [String]()

```

`ViewDidLoad`内でインスタンスを生成する。

```Swift:TalkRoomViewController.swift

    databaseRef = Database.database().reference()

```

データベース読み込み時に、`roomData`パラメータに値を追加して、テーブルの再描画を実施する。

```Swift:TalkRoomViewController.swift
        databaseRef.observe(.childAdded, with: { snapshot in
            self.roomData.append(snapshot.key)
            self.tableView.reloadData()
        })
```

セルの数を変更 ※(データの数)+(新規追加用セルの数)

```Swift:TalkRoomViewController.swift

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return roomData.count + 1
    }

```

データから名前を取得して表示する。

```Swift:TalkRoomViewController.swift

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        switch  indexPath.row {
        case ..<roomData.count:
            cell.textLabel?.text = roomData[indexPath.row]
        default:
            cell.textLabel?.text = "+ Create New Room"
            cell.textLabel?.textColor = UIColor.blue
        }
        return cell
    }

```

Cellタップ時のメソッドを変更

```Swift:TalkRoomViewController.swift

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        switch indexPath.row {
        case ..<roomData.count:
            self.performSegue(withIdentifier: "showRoomView", sender: nil)
        default:
            self.performSegue(withIdentifier: "modalCreateRoomView", sender: nil)
            return
        }
    }

```

# 13. 画面遷移時に部屋情報を遷移先の画面に渡す

`ViewController.swft`に部屋情報を受け取る用のパラメータを作成する。

```Swift:ViewController.swift

var roomName: String?

```

画面遷移前に呼ばれるメソッドで次の画面に値を設定する処理を追加

```Swift:TalkRoomViewController.swift

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard segue.identifier == "showRoomView", let targetVC = segue.destination as? ViewController else {
            return
        }
        
        if let roomName = sender as? String {
            targetVC.roomName = roomName
        }
    }

```

Cell選択時に、選択されたCellの情報を渡す処理を追加

```Swift:TalkRoomViewController.swift

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        switch indexPath.row {
        case ..<roomData.count:
            let roomName = roomData[indexPath.row]
            self.performSegue(withIdentifier: "showRoomView", sender: roomName)
        default:
            self.performSegue(withIdentifier: "modalCreateRoomView", sender: nil)
            return
        }
    }
```

# 14. チャット画面のデータベース読み込み/書き込み処理を修正
ルーム名をキーとして、データを取得する。

```Swift:ViewController.swift

 databaseRef = Database.database().reference().child(roomName!)

```