Firestoreを使えばバックエンドが楽に実装できるという事で、Firestoreを触ってみました。
導入がとても楽で、使いこなせれば爆速でアプリ開発出来そうだなという印象です。
#1. Cloud Firestore プロジェクトの作成
こちらの公式ドキュメント内「Cloud Firestore プロジェクトを作成する」を参考にFirestoreのセットアップを行なっていきます。
https://firebase.google.com/docs/firestore/quickstart?hl=ja
ドキュメント通りに進めていけば、特に問題なくプロジェクトを作成できると思います。
今回は簡易的にFirestoreを使いたい為、Authentication のログインプロバイダにて、「匿名」を有効にします。
こちらも簡易的に使いたい為、テストモードで開始します。
#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はメッセージを送受信表示する為に必要最低限の物を配置してあります。
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. 動作確認
メッセージが送信されるとデータベースの変更を取得し、TableViewが更新されている事がわかります。
Firebase コンソールからもデータが送信されていることが確認できます。まとめ
Firestoreを用いれば、とても簡単にデータの書き取り、読み取りができる。
用いたソースはGithubに載せておきます。
https://github.com/taka011002/firestore_test_ios