Help us understand the problem. What is going on with this article?

iOSではじめてのFirestore [Swift]

Firestoreを使えばバックエンドが楽に実装できるという事で、Firestoreを触ってみました。
導入がとても楽で、使いこなせれば爆速でアプリ開発出来そうだなという印象です。

1. Cloud Firestore プロジェクトの作成

こちらの公式ドキュメント内「Cloud Firestore プロジェクトを作成する」を参考にFirestoreのセットアップを行なっていきます。

https://firebase.google.com/docs/firestore/quickstart?hl=ja

ドキュメント通りに進めていけば、特に問題なくプロジェクトを作成できると思います。
スクリーンショット 2019-05-04 2.52.34.png

今回は簡易的にFirestoreを使いたい為、Authentication のログインプロバイダにて、「匿名」を有効にします。
スクリーンショット 2019-05-04 2.59.57.png

こちらも簡易的に使いたい為、テストモードで開始します。
スクリーンショット 2019-05-04 3.03.28.png

2. iOSアプリへFirebaseの導入

iOSアプリ側の導入の方も公式ドキュメント通りに進めていけば、特に問題なく導入できると思います。

Firestoreをアプリで使用するにはFirebaseの導入が必要な為、導入していきます。

https://firebase.google.com/docs/ios/setup?hl=ja
https://firebase.google.com/docs/auth/ios/custom-auth?hl=ja

ドキュメント通りに構成ファイルGoogleService-Info.plistを作成し、プロジェクトへ追加。
Podfile に下記を追加し、pod install

pod 'Firebase/Core'
pod 'Firebase/Auth'

認証を行う為に、AppDelegate内にてimport Firebaseし、次を追加

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    FirebaseApp.configure()
    Auth.auth().signInAnonymously()

    return true
}

これでFirebaseの導入ができました。

3. iOSアプリへFirestoreの導入

Firebaseの導入ができていれば、Podfile に下記を追加しpod installを行うだけでFirestoreの利用が可能になります。

pod 'Firebase/Firestore'

4. Firestoreを使ってみる

今回はとりあえずデータの書き取り、読み取りを行なってみたい為メッセージの送受信をできる様にしてみます。

UIはメッセージを送受信表示する為に必要最低限の物を配置してあります。
スクリーンショット 2019-05-04 4.23.59(2).png

StoryBoard に対応したソースはこちらになります。

import UIKit
import Firebase

class ChatViewController: UIViewController {

    struct Message {
        var senderId: String
        var name: String
        var message: String
    }

    @IBOutlet weak var chatTableView: UITableView!
    @IBOutlet weak var nameTextField: UITextField!
    @IBOutlet weak var messageTextField: UITextField!

    private var messages : [Message] = []
    private var messageListener: ListenerRegistration?

    override func viewDidLoad() {
        super.viewDidLoad()
        chatTableView.register(UINib(nibName: "ChatTableViewCell", bundle: nil), forCellReuseIdentifier: "ChatTableViewCell")
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.messageListener = Firestore.firestore().collection( "chat" ).order( by: "date" ).addSnapshotListener { snapshot, e in
            if let snapshot = snapshot {

                self.messages = snapshot.documents.map{ message -> Message in
                    let data = message.data()
                    return Message(senderId: data["sender_id"] as! String, name: data["name"] as! String, message: data["text"] as! String)
                }
                self.chatTableView.reloadData()
            }
        }
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear( animated )
        if let mUnsubscribe = messageListener { mUnsubscribe.remove() }
    }

    @IBAction func trappedSendButton(_ sender: Any) {
        sendChatMessage(name: nameTextField.text ?? "", message: messageTextField.text ?? "")
    }

    private func sendChatMessage(name: String, message: String) {
        guard let id = UIDevice.current.identifierForVendor?.uuidString else { return }

        let dataStore = Firestore.firestore()
        dataStore.collection("chat").addDocument(data: [
            "text": message,
            "name": name,
            "sender_id": id,
            "date": Date()
        ]) { err in
            DispatchQueue.main.async {
                if let err = err {
                    print("Error writing document: \(err)")
                } else {
                    self.messageTextField.text = ""
                }
            }
        }
    }

}

extension ChatViewController : UITableViewDelegate, UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ table: UITableView, numberOfRowsInSection section: Int) -> Int {
        return  messages.count
    }

    func tableView(_ table: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = table.dequeueReusableCell(withIdentifier: "ChatTableViewCell",for: indexPath) as! ChatTableViewCell
        let message = messages[indexPath.row]
        cell.set(name: message.name)
        cell.set(message: message.message)
        return cell
    }

}

こちらの部分でデータベースの読み取り、変更を取得しています。

Firestore.firestore().collection( "chat" ).order( by: "date" ).addSnapshotListener{ snapshot, e in }

こちらの部分でメッセージの送信を行なっております。

private func sendChatMessage(name: String, message: String) {
        guard let id = UIDevice.current.identifierForVendor?.uuidString else { return }

        let dataStore = Firestore.firestore()
        dataStore.collection("chat").addDocument(data: [
            "text": message,
            "name": name,
            "sender_id": id,
            "date": Date()
        ]) { err in
            DispatchQueue.main.async {
                if let err = err {
                    print("Error writing document: \(err)")
                } else {
                    self.messageTextField.text = ""
                }
            }
        }
    }

5. 動作確認

先ほどのコードで実行したものがこちらになります。
simu.gif

メッセージが送信されるとデータベースの変更を取得し、TableViewが更新されている事がわかります。

スクリーンショット 2019-05-04 4.38.21.png
Firebase コンソールからもデータが送信されていることが確認できます。

まとめ

Firestoreを用いれば、とても簡単にデータの書き取り、読み取りができる。

用いたソースはGithubに載せておきます。
https://github.com/taka011002/firestore_test_ios

参考

Firebase / Firestore を使って簡単な Chat を作ってみる。(iOS)

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away