【Swift】 Firebaseでリアルタイム更新のチャット機能を作ってみる【Realtime Database】
Firebaseにはプッシュ通知の機能や、ユーザー認証、リアルタイムデータベースなど様々な機能があります。
今回はFirebaseの最初の製品である「Firebase Real-time Database」を使って簡単かつシンプルなチャットアプリを作りました。
環境
・MacOS Ventura 13.0
・Xcode 14.2
・Swift version 5.7.2
構成、設定等
【Firebase】
・プロジェクト名: SampleProject
【iOS】
・プロジェクト名: SampleFirebase
・画面構成:1画面(チャットの画面のみ)
1. アカウント作成とFirebaseプロジェクトの作成
Googleアカウントがあれば簡単に作成可能です。
アカウントの作成が完了したら「使ってみる」をクリックします。
続いてプロジェクトの追加をクリックします。
Firebaseのプロジェクト名を入力して続行を押します。
今回はSampleProjectとしました。
このあとGoogleアナリティクスの有効化画面が表示されますが使用しないため、チェックを外して続行します。
プロジェクトの作成が完了しました。
2. SDK設定
プロジェクトの作成が完了したらiOS+をクリックします。
手順に従って進めていきます。
2-1. ①アプリの登録
AppleのバンドルID: Xcodeから確認します。
アプリのニックネーム(省略可)
App Store ID(省略可)
バンドルIDはXcodeのここから確認可能です。
2-2. ②設定ファイルのダウンロード
GoogleSevice-info.plistをダウンロードしてプロジェクト内にコピーします。
2-3. Firebase SDKの追加
今回はCocoaPodsを使用しました。CocoaPodsをインストールしてから以下の作業を行います。
例)
cd /Users/ユーザー名/Documents/Projects/SampleFirebase/SampleFirebase.xcodeproj
〇〇.xcodeprojを削除してプロジェクトのフォルダ直下に移動します。
cd /Users/ユーザー名/Documents/Projects/SampleFirebase
プロジェクトフォルダに移動したらプロジェクトフォルダ内にpodfileを作成
pod init
podfileを開く
open podfile
pod file内に[FirebaseDatabase]を追加。
※RealTimeDatabaseのみ利用するため。
pod 'FirebaseDatabase'
ライブラリのインストール
pod install
これでFirebaseSDKの導入が完了しました。
プロジェクトを一旦閉じて白色のファイルから開き直します。
ファイル名が.xcodeprojではなく.xcworkspaceとなっています。
プロジェクトを開いたら問題なくビルドできるか確認します。
2-4. RealtimeDatabaseの作成
全て完了したのでコンソールに進みます。
Realtime Databaseを探して、データベースを作成を押します。
ロケーションを選択
データベースの設定はテストモードにしました。
これでFirebase側の設定は完了です。
3. チャット機能を作る
ここからはXcodeでチャットの機能を作っていきます。
3-1. まずはじめに
import FirebaseCore
FirebaseApp.configure()
追加する場所はこちらです。
import UIKit
//追加
import FirebaseCore
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//追加
FirebaseApp.configure()
return true
}
}
3-2. 画面レイアウトの作成
続いてレイアウトの作成していきます。
配置したUIパーツと役割の説明
・TextView → リアルタイム更新のチャットのメッセージ表示
・TextField → 送信者の名前入力
・TextField → 送信者のメッセージの入力
・Button → ボタンタップでメッセージの送信
レイアウトが完成したら右クリックドラッグアンドドロップでOutletとActionをコードに追加します。
TextViewとTextFieldにはOutlet、ButtonにはActionを設定します。
設定が終わったらFirebaseを使うためのコードを書いていきます。
ViewControllerファイルでFirebaseDatabaseをimportします。
import FirebaseDatabase
ルートの指定をします。スクリーンショットの赤色の部分がルートだそうです。
var databaseRef: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
//ルートの指定
databaseRef = Database.database().reference()
}
これでデータベースにアクセスできるようになりました。
ここからは実際にデータベースを追加してみます。
送信ボタンのAction内で送信者の名前とメッセージの内容を送信しています。
//TextFieldに入力したテキストをセット
let messageInfo = ["name": nameTextField.text, "message": messageTextField.text]
//ルート→chat_room→AutoID(自動でID生成)の下に名前とメッセージデータを書き込み
self.databaseRef.child("chat_room").child(roomID).childByAutoId().setValue(messageInfo)
新しいデータが追加されたらチャット欄に反映する処理を作成します。
observeはデータの監視、.childAddedの部分は監視する条件の指定(データが追加されたとき)、snapshotは追加データを表します。
func observeChatMessage(databaseRef: DatabaseReference) {
//snapshotが追加データを表します
databaseRef.child("chat_room").child(roomID).observe(.childAdded) { snapshot in
//データのnilチェック、データが存在する場合key:valueの形で受け取ります
if let value = snapshot.value as? [String: Any] {
//名前とメッセージを指定したkeyで受け取ります。ない場合は空文字""としています。
let name = value["name"] as? String ?? ""
let message = value["message"] as? String ?? ""
//チャットのメッセージ表示用のTextViewにテキストを追加します。
self.realTimeChatTextView.text = self.realTimeChatTextView.text + "\n\(name):\(message)"
}
}
}
全体のコード
import UIKit
import FirebaseDatabase
class ViewController: UIViewController, UITextFieldDelegate {
var databaseRef: DatabaseReference!
//チャットルームのID 固定値としました
let roomID = "room1"
@IBOutlet weak var realTimeChatTextView: UITextView!
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var messageTextField: UITextField!
@IBAction func sendButtonAction(_ sender: Any) {
//TextFieldに入力したテキストをセット
let messageInfo = ["name": nameTextField.text, "message": messageTextField.text]
//ルート→chat_room→AutoID(自動でID生成)の下に名前とメッセージデータを書き込み
self.databaseRef.child("chat_room").child(roomID).childByAutoId().setValue(messageInfo)
}
override func viewDidLoad() {
super.viewDidLoad()
nameTextField.delegate = self
messageTextField.delegate = self
//ルート
databaseRef = Database.database().reference()
//初回データセット+追加データの監視
observeChatMessage(databaseRef: databaseRef)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool{
// キーボードを閉じる
textField.resignFirstResponder()
return true
}
func observeChatMessage(databaseRef: DatabaseReference) {
//snapshotが追加データを表します
databaseRef.child("chat_room").child(roomID).observe(.childAdded) { snapshot in
//データのnilチェック、データが存在する場合key:valueの形で受け取ります
if let value = snapshot.value as? [String: Any] {
//名前とメッセージを指定したkeyで受け取ります。ない場合は空文字""としています。
let name = value["name"] as? String ?? ""
let message = value["message"] as? String ?? ""
//チャットのメッセージ表示用のTextViewにテキストを追加します。
self.realTimeChatTextView.text = self.realTimeChatTextView.text + "\n\(name):\(message)"
}
}
}
}
3-3. 実行結果
Firebase
4. まとめ
いかがでしたでしょうか。
今回はFirebaseを使用して簡単なチャット機能を作成してみました。
正直作り始める前はこれだけ少ないコード量で実装できるとは思っていませんでした。
FirebaseであればSQLの知識がなくてもデータを扱えます。
Realtime Databaseを初めて扱う方の参考になれば幸いです。