私のアプリはFirebaseを使用してデータを同期および復元します。 setValue:withCompletionBlock:
メソッドを使用して、Firebaseオブジェクトを挿入、更新、削除します。このメソッドはCoreDataが保存されるたびに呼び出されるため、ローカルのすべての変更をFirebaseに同期します
- (void) setValue:(id)value withCompletionBlock:(void (^)(NSError* error, Firebase* ref))block;
同期すると、すべてのローカルデータがFirebaseにアップロードされ、復元するとローカルデータがFirebaseデータに置き換えられます。
- (void) observeSingleEventOfType:(FEventType)eventType withBlock:(void (^)(FDataSnapshot* snapshot))block;
私はFEventTypeValue
を観察し、FDataSnapshot
を使用してFirebaseからデータを取得し、ローカルデータを復元します。
したがって、persistence
をFirebaseに設定するまで、すべてが完璧に機能します。
[Firebase setOption:@"persistence" to:@YES];
persistence
がオンになっているときに、更新、つまりオブジェクトをFirebaseに挿入して復元すると、挿入前のデータが復元されます。つまり、新しく挿入されたオブジェクトは復元されません。ただし、再度復元すると、挿入されたオブジェクトが復元されます。オブジェクトが削除されたときにも同じことが起こります。削除したオブジェクトは、初めて復元すると再び表示され、もう一度復元すると消えます。 Firebaseデータビューで、Firebaseオブジェクトが正しく挿入または削除されていることがわかります。
ここで何が間違っているのかわかりません。復元したときにのみ問題が発生します。 Firebaseキャッシュがこの復元の問題を引き起こしていると思います。復元する前にFirebaseのキャッシュをクリアすることを考えています。私の質問は
[注:Realtime Databaseの代わりにCloud Firestoreを使用するオプションがある場合、オフラインサポートの方がはるかに優れています。 .get()を実行すると、サーバーから最新のデータを自動的にフェッチし、オフラインの場合はキャッシュされたデータのみを使用します。サーバーまたはキャッシュからデータを取得するように具体的に要求することもできます。]
残念ながらこれは予想される動作です。おそらく、observeSingleEventOfTypeの代わりにobserveEventOfTypeを使用することで回避できます。
基本的に、データを観察するときはいつでも、最初に永続キャッシュからデータをプルします。そのデータは、Firebaseから最後に受信したデータになります。 observeEventOfTypeの代わりにobserveSingleEventOfTypeを使用しているため、Firebaseから定期的な更新を受信することはなく、キャッシュしたデータには実際に書き込んだ最新のデータが含まれていません。
簡単な修正として、問題のデータにobserveEventOfTypeを追加するだけでよい場合があります。イベントを実際に操作する必要はありません。ただし、常にそれらをリッスンすると、アプリはfirebaseから最新のデータを取得し、observeSingleEventOfTypeを呼び出すと、最新のデータがキャッシュされていると確信できます。
snap.metadata.fromCache
フラグを使用して、値がキャッシュからのものかどうかを確認できます。キャッシュ値とサーバーからの値が一致する場合、以下のincludeMetadataChanges
フラグを追加しない限り、onSnapshotを2回起動しないことに注意してください。代わりに、metadata.fromCache
フラグを使用して1回のみ起動します。 true
に設定されます。
db.collection('users').doc(uid).onSnapshot({ includeMetadataChanges: true }, (snap) => {
if (!snap.metadata.fromCache) {
const user = snap.data();
// Code here
}
})