Firebase コメント機能を実装しよう！

こんにちは！🐶

今回はコメント機能を実装したいと思います！

#下準備

はい！では下準備として、まずストリーボードを作っていきましょう！
![スクリーンショット 2021-06-09 21.44.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694910/503fccd3-93ee-4f87-bfe5-0b8476cd6e5f.png)

コメント画面用のViewControllerを設置し、その上にtableViewを配置しましょう！そして画面下部にコメントを送信するためのtextFieldと送信ボタンを配置しましょう！
![スクリーンショット 2021-06-09 22.24.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694910/a5d949a3-6d8d-b519-1642-7dcdee5dbb84.png)

そしてコメントが投稿されるセルはカスタムセルを使うので、カスタムセルを用意しましょう！
カスタムセルの上にはユーザー画像のimageViewとユーザーネームのlabelとコメント内容のlabelを配置しましょう！
またカスタムセルのクラスのidentifierをCommentCellに設定しておきましょう！

![スクリーンショット 2021-06-09 22.27.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694910/941528bf-a8d3-e8b9-b51f-e100849f7bde.png)


新しくCommentViewContorollerを配置し、必要な素材をコードに書きましょう！👇

```php:CommentViewContoroller
import UIKit
import Firebase
import FirebaseFirestore



class CommentViewController: UIViewController {
    
    @IBOutlet weak var textfield: UITextField!
    
    @IBOutlet weak var sendButton: UIButton!
    
    @IBOutlet weak var tableView: UITableView!
    
    let db = Firestore.firestore()
    
    var postId = String()
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(UINib(nibName: "CommentTableViewCell", bundle: nil), forCellReuseIdentifier: "CommentCell")
        
        // Do any additional setup after loading the view.
    }
    
    @IBAction func sendAction(_ sender: Any) {
        //textFieldにテキストが入っていなかったらリターンする
        if textfield.text?.isEmpty == true{
            return
        }
        //Post下にcommentsコレクションを作る
        db.collection("Post").document(postId).collection("comments").document().setData(["userId":Auth.auth().currentUser?.uid as Any,"comment":textfield.text! as Any,"postDate":Date().timeIntervalSince1970])
        //送信後はからにする
        textfield.text = ""
        
    }
}

//tableVIewの設定
extension CommentViewController : UITableViewDelegate,UITableViewDataSource {
    
    //tableViewのcellの数
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    }
    //tableViewCellの中身
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
    }
    
    
    //tablaViewの高さ設定
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 200
    }
    
}

```

#実装しよう！
それでは、コメント機能を実装していきましょう！

まずは、送信機能をつけていきます！

送信機能をつけるには、どの投稿にコメントされたのかをわからなければなりません。
その為に、前の画面（ViewContoroller)から、値渡しを行いましょう！

ではViewControllerのextensionで設定していたtableViewの設定の中に、以下のコードを追加しましょう！

```php:ViewController 
 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
           //画面遷移,"commentVC"という名前をComenntViewControllerのidentifierに設定
           let commentVC = self.storyboard?.instantiateViewController(withIdentifier: "commentVC") as! CommentViewController
           //postIdに配列の選択した投稿のpostIdを持っていく
           commentVC.postId = postArray[indexPath.row].postId
           self.navigationController?.pushViewController(commentVC, animated: true)
       }
```
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)はtableViewが選択されたときに呼ばれるものです。
今回は、選択したら画面遷移を行いたいので、画面遷移のコードを書いています。このとき、"commentVC"という名前をComenntViewControllerのidentifierに設定することでComenntViewContorollerに遷移することができます！
![スクリーンショット 2021-06-09 22.04.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694910/8b8ff36e-197a-efea-5f0a-b03e17581cb1.png)

また今回は選択した投稿のpostIdを値渡しすることで、次の画面でコメントするときにその投稿の情報にコメントを残すことができます。

ですので、この値を受け入れる為にComenntViewContorollerにpostIdという変数を用意してあげましょう！

```php:CommentViewContoroller

class CommentViewController: UIViewController {
    
    @IBOutlet weak var textfield: UITextField!
    
    @IBOutlet weak var sendButton: UIButton!
    
    let db = Firestore.firestore()
    
    var postId = String()
    
    

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
    
    @IBAction func sendAction(_ sender: Any) {
       
       }
}
```

値渡しが完了したところで、早速コードを書いていきましょう！
まず、コメント送信のコードを書いていくとこのようになります👇

```php:CommentViewContoroller

class CommentViewController: UIViewController {
    
 @IBAction func sendAction(_ sender: Any) {
        //textFieldにテキストが入っていなかったらリターンする
        if textfield.text?.isEmpty == true{
            return
        }
        //Post下にcommentsコレクションを作る
        db.collection("Post").document(postId).collection("comments").document().setData(["userId":Auth.auth().currentUser?.uid as Any,"comment":textfield.text! as Any,"postDate":Date().timeIntervalSince1970])
        //送信後はからにする
        textfield.text = ""
        
       }
```

まずいつもと違うところは、Postコレクションの下に新しくcommentsコレクションを作っているという点です。
こうすることで、Postコレクションにまとめてコメント情報を格納することができます。
実際にデータベースを見てみるとわかると思います👇

このようにPostコレクションの中に新しくcommentコレクションが作られています。
![スクリーンショット 2021-06-09 22.55.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694910/2dfe2d7a-aae0-b9d1-941a-2ef8ba25d891.png)


これでコメントをデーターベースに送信することができました！！

#コメントを呼び出そう！
コメントをデータベースに送ることができたら次は、それをtableViewに表示させましょう！
まず、データを読み取るコードは以下になります。

```php:CommentViewController
   func loadData(){
        db.collection("Post").document(postId).collection("comments").order(by: "postDate").addSnapshotListener { (result, error) in
            if error != nil {
                print("データ呼び出し失敗")
            } else {
                print("データ呼び出し成功")
                if let documents = result?.documents {
                    //配列の初期化
                    self.commentArray = []
                    //持ってきたデータを一つ一つ配列に保存
                    for document in documents {
                        let data = document.data()
                        
                        let comment = Comment(userId: data["userId"] as! String,comment: data["comment"] as! String,Date:["commentDate"]as! Double)
                        //postArray配列に追加
                        self.commentArray.append(comment)
                        
                    }
                    
                    //古いものを下にする
                    self.commentArray.reverse()
                    self.tableView.reloadData()
                }
                
            }
        }
        
    }

```

いつもと違うところは、addSnapshotListenerが使われているところです。addSnapshotListenerとは、データベースに変更が加えられたらそれをすぐ反映したいときに使います。
ここでいえば、コメントが追加されたら、すぐさま、セルに反映されます。

またドキュメント（）の中にpostIdを指定することで、特定の投稿に対して、commentコレクションが作られます。ここでいえば、選んだ投稿に対して、commentコレクションが作られます。

投稿の情報を持ってくることができたらそれを、セルに表示させましょう！👇
ここでは、同時にユーザー情報を持ってきています！


```php:CommentViewController
//tableVIewの設定
extension CommentViewController : UITableViewDelegate,UITableViewDataSource {
    
    //tableViewのcellの数
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return commentArray.count
    }
    //tableViewCellの中身
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CommentCell", for: indexPath) as! CommentTableViewCell
        cell.commentLabel.text = commentArray[indexPath.row].comment
        
        
        //ユーザー画像をセルに配置
        db.collection("Users").document(commentArray[indexPath.row].userId).getDocument { (result, error) in
            if error != nil {
                print("ユーザー情報取得失敗")
            }
            print("ユーザー情報取得成功")
            let data = result!.data()
            let user = User(userName: data!["userName"] as! String, profileImage: data!["profileImage"]  as! String, introduction: data!["introduction"] as! String)
            cell.userNameLabel.text = user.userName
            //ユーザー画像が設定されていれば
            if let userImageUrl = URL(string:user.profileImage ?? "") {
                Nuke.loadImage(with: userImageUrl, into: cell.userImageView)
            }
            
        }
        return cell
    }
    
```

ユーザー情報の取得は以前したのと全く同じです！

これでコメント機能ができました！