【SwiftUI/Firebase】Realtime Databaseでオフラインキャッシュを有効にする方法

この記事からわかること
- SwiftでFirebaseのRealtime Databaseでオフラインでのローカルキャッシュを有効にする方法
- isPersistenceEnabledプロパティの設定方法と記述場所
- ネットワーク接続の可否を識別するには?
index
[open]
\ アプリをリリースしました /
公式リファレンス:Appleプラットフォームのオフライン機能
Realtime Databaseでのオフラインデータ表示
FirebaseのRealtime Databaseではオフライン環境でも永続的なデータの表示が可能になっているのが大きなメリットでもあります。
仕組みとしてはオンライン時に取得したいデータをデバイス内にローカルキャッシュとして保存しておくことで最終読み込み時のデータを表示できる仕組みになっています。また更新などの操作もローカルキャッシュに対して行うことができるのでユーザーはオフラインを意識することなく操作できるようになっています。
そして再度オンラインになった際に書き込み処理や変更処理などをが自動で反映されるようになっています。
ですがRealtime Databaseではオフライン環境でのデータ表示を有効にするには設定を明示的にする必要があります。
Swift UIでオフラインを有効にする方法
オフライン時のためにデータキャッシュを有効にするには以下のようにdatabaseインスタンスのisPersistenceEnabledプロパティの設定を変更する必要があります。
Database.database().isPersistenceEnabled = true
Swift UIを使用している場合はアプリプロジェクトファイルのdelegateの中に記述します。importも忘れずにしておきます。
import FirebaseDatabase // 追加
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
// 追加
Database.database().isPersistenceEnabled = true
return true
}
}
これでデータがローカルにも保存されオフライン環境になってもデータ表示を永続的に行えるようになりました。
ネットワーク接続の可否を識別する
さらにRealtime Databaseではネットワーク接続の可否を簡単に識別できるような機能が組み込まれています。
/.info/connected
内にユーザーの接続状態を真偽値で常に保持されるようになっているので、その値によって識別可能です。
let connectedRef = Database.database().reference(withPath: ".info/connected")
connectedRef.observe(.value, with: { snapshot in
if snapshot.value as? Bool ?? false {
print("Connected")
} else {
print("Not connected")
}
})
ネットワーク接続によって読み込み先を分岐させる
ネットワーク接続の可否によってサーバーからデータを読むか明示的にローカルキャッシュからデータを読み込むかを分岐させる処理を実装してみます。
// ネット接続状況によって処理を分岐させる
func checkConnectedCallLoading(){
let connectedRef = Database.database().reference(withPath: ".info/connected")
connectedRef.observe(.value, with: { snapshot in
if snapshot.value as? Bool ?? false {
// print("Connected")
self.loadingData()
} else {
// print("Not connected")
self.localLoadingData()
}
})
}
// オンライン時のデータ読み込み
func loadingData() {
ref.child("users").child(currentUserID).getData(completion: { error, snapshot in
guard error == nil || snapshot != nil else {
print(error!.localizedDescription)
return
}
})
}
// オフライン時のキャッシュデータ読み込み
func localLoadingData() {
ref.child("users").child(currentUserID).observeSingleEvent(of: .value, with: { snapshot in
})
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。