إمكانات وضع عدم الاتصال بالإنترنت على منصات Apple

تعمل تطبيقات Firebase حتى إذا فقد تطبيقك الشبكة مؤقتًا. الاتصال. بالإضافة إلى ذلك، يوفر Firebase أدوات للاحتفاظ بالبيانات محليًا، وإدارة التواجد ووقت الاستجابة.

ثبات القرص

تتعامل تطبيقات Firebase مع الانقطاعات المؤقتة في الشبكة تلقائيًا. تتوفّر البيانات المخزّنة مؤقتًا عندما تكون غير متصل بالإنترنت، ويعيد Firebase إرسال أي عمليات كتابة. عند استعادة اتصال الشبكة.

عند تفعيل خاصية الاحتفاظ بالقرص، يكتب تطبيقك البيانات محليًا على حتى يحافظ تطبيقك على حالته أثناء عدم الاتصال بالإنترنت، حتى إذا كان المستخدم أو نظام التشغيل يعيد تشغيل التطبيق.

يمكنك تفعيل ميزة تثبيت القرص باستخدام سطر واحد فقط من الرمز.

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
Database.database().isPersistenceEnabled = true

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
[FIRDatabase database].persistenceEnabled = YES;

سلوك الاستمرارية

من خلال تفعيل ميزة الثبات، أي بيانات يقوم برنامج قاعدة بيانات Firebase في الوقت الفعلي تتم مزامنته أثناء استمرار الاتصال بالإنترنت على القرص وإتاحتها في وضع عدم الاتصال، حتى عندما يعيد المستخدم أو نظام التشغيل تشغيل التطبيق. هذا يعني أن كما لو كان على الإنترنت باستخدام البيانات المحلية المخزنة في ذاكرة التخزين المؤقت. سيستمر تنشيط استدعاءات المستمعين للحصول على التحديثات المحلية.

يحتفظ برنامج قاعدة بيانات Firebase في الوقت الفعلي تلقائيًا بقائمة انتظار لجميع كتابة العمليات التي يتم إجراؤها أثناء عدم اتصال التطبيق بالإنترنت. عند تمكين الثبات، يتم أيضًا حفظ قائمة الانتظار هذه على القرص حتى يكون جميع عندما تتوفر كتاباتك عندما يستخدم المستخدم أو نظام التشغيل لإعادة تشغيل التطبيق. عندما يستعيد التطبيق الاتصال، فإن جميع يتم إرسال العمليات إلى خادم قاعدة بيانات Firebase في الوقت الفعلي.

إذا كان تطبيقك يستخدم مصادقة Firebase، يحتفظ عميل قاعدة بيانات Firebase في الوقت الفعلي بمصادقة المستخدم الرمز المميز عبر عمليات إعادة تشغيل التطبيق. إذا انتهت صلاحية الرمز المميّز للمصادقة عندما يكون تطبيقك غير متصل بالإنترنت، سيتم إيقاف البرنامج مؤقتًا. كتابة العمليات حتى يعيد التطبيق مصادقة المستخدم، وإلا عمليات الكتابة بسبب قواعد الأمان.

الحفاظ على إعادة تحميل البيانات

وتزامن قاعدة بيانات Firebase في الوقت الفعلي وتخزّن نسخة محلية من المستمعين النشطين. بالإضافة إلى ذلك، يمكنك الاحتفاظ بمواقع جغرافية محددة متزامنًا.

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
let scoresRef = Database.database().reference(withPath: "scores")
scoresRef.keepSynced(true)

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
FIRDatabaseReference *scoresRef = [[FIRDatabase database] referenceWithPath:@"scores"];
[scoresRef keepSynced:YES];

يعمل عميل قاعدة بيانات Firebase في الوقت الفعلي تلقائيًا على تنزيل البيانات في هذه المواقع ويحافظ على مزامنتها حتى إذا كان المرجع المستمعين النشطين. يمكنك إيقاف المزامنة مرة أخرى باستخدام السطر التالي من التعليمة البرمجية.

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
scoresRef.keepSynced(false)

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
[scoresRef keepSynced:NO];

بشكل تلقائي، يتم تخزين 10 ميغابايت من البيانات التي تمت مزامنتها سابقًا مؤقتًا. يجب أن يكون هذا كافيًا لمعظم التطبيقات. إذا تخطت ذاكرة التخزين المؤقت حجمها الذي تم إعداده، فإن قاعدة بيانات Firebase في الوقت الفعلي تزيل نهائيًا البيانات المستخدَمة مؤخرًا. لا تتم الإزالة النهائية للبيانات التي يتم الاحتفاظ بها متزامنة من ذاكرة التخزين المؤقت.

الاستعلام عن البيانات بلا اتصال بالإنترنت

تخزِّن قاعدة بيانات Firebase في الوقت الفعلي البيانات التي يتم عرضها من استعلام لاستخدامها. عندما تكون غير متصل بالإنترنت. بالنسبة للاستعلامات التي تم إنشاؤها أثناء وضع عدم الاتصال، تواصل قاعدة بيانات Firebase في الوقت الفعلي العمل مع البيانات التي تم تحميلها مسبقًا. إذا لم يتم تحميل البيانات المطلوبة، يتم تحميل قاعدة بيانات Firebase في الوقت الفعلي من ذاكرة التخزين المؤقت المحلية. عندما يكون اتصال الشبكة متاحًا مرة أخرى، يتم تحميل البيانات وستعكس الاستعلام.

على سبيل المثال، تطلب هذه التعليمة البرمجية لآخر أربعة عناصر في "قاعدة بيانات Firebase في الوقت الفعلي" للنتائج

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
let scoresRef = Database.database().reference(withPath: "scores")
scoresRef.queryOrderedByValue().queryLimited(toLast: 4).observe(.childAdded) { snapshot in
  print("The \(snapshot.key) dinosaur's score is \(snapshot.value ?? "null")")
}

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
FIRDatabaseReference *scoresRef = [[FIRDatabase database] referenceWithPath:@"scores"];
[[[scoresRef queryOrderedByValue] queryLimitedToLast:4]
    observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) {
      NSLog(@"The %@ dinosaur's score is %@", snapshot.key, snapshot.value);
    }];

لنفترض أنّ المستخدم فقد الاتصال بالإنترنت وانقطع الاتصال بالإنترنت ثم أعاد تشغيل التطبيق. أثناء عدم اتصال التطبيق بالإنترنت، يطلب التطبيق آخر عنصرين من الموقع نفسه. سيعرض هذا الاستعلام آخر عنصرين بنجاح لأن التطبيق حمّل جميع العناصر الأربعة في الاستعلام أعلاه.

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
scoresRef.queryOrderedByValue().queryLimited(toLast: 2).observe(.childAdded) { snapshot in
  print("The \(snapshot.key) dinosaur's score is \(snapshot.value ?? "null")")
}

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
[[[scoresRef queryOrderedByValue] queryLimitedToLast:2]
    observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) {
      NSLog(@"The %@ dinosaur's score is %@", snapshot.key, snapshot.value);
    }];

في المثال السابق، يطرح عميل قاعدة بيانات Firebase في الوقت الفعلي "تمت إضافة تابعة" التي تضم أعلى ديناصورين من النقاط، وذلك باستخدام تم الاحتفاظ بذاكرة التخزين المؤقت. لكنها لن تزيد "القيمة" حدث، نظرًا لأن التطبيق يحتوي على لم تنفذ هذا الاستعلام أثناء الاتصال بالإنترنت.

إذا طلب التطبيق العناصر الستة الأخيرة أثناء عدم الاتصال، فسيحصل "تمت إضافة تابعة" الأحداث للعناصر الأربعة المخزنة مؤقتًا على الفور. عندما الإنترنت مرة أخرى، فسيجري برنامج قاعدة بيانات Firebase في الوقت الفعلي مع الخادم ويتم الحصول على آخر عنصرين "تابعين" و 'value' أحداث للتطبيق.

التعامل مع المعاملات بلا إنترنت

يتم وضع أي معاملات يتم إجراؤها عندما يكون التطبيق بلا اتصال بالإنترنت في قائمة الانتظار. بعد أن يستعيد التطبيق الاتصال بالشبكة، يتم إرسال المعاملات إلى خادم قاعدة بيانات الوقت الفعلي.

إدارة التواجد

غالبًا ما يكون من المفيد في تطبيقات الوقت الفعلي اكتشاف الوقت الذي يستغرقه العملاء الاتصال وقطع الاتصال. على سبيل المثال، يمكنك أن تريد وضع علامة "غير متصل" على المستخدم عندما ينقطع اتصال عميله.

يوفر عملاء قاعدة بيانات Firebase أساسيات بسيطة يمكنك استخدامها الكتابة في قاعدة البيانات عندما ينقطع اتصال العميل بقاعدة بيانات Firebase الخوادم. وتحدث هذه التحديثات سواء انفصل العميل عن الخدمة أم لا لذا يمكنك الاعتماد عليها لتنظيف البيانات حتى إذا انقطع الاتصال أو تعطل عميل ما. جميع عمليات الكتابة، بما في ذلك الإعداد وتحديثه وإزالته، عند قطع الاتصال.

فيما يلي مثال بسيط لكتابة البيانات عند الفصل باستخدام المجموعة الأساسية onDisconnect:

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
let presenceRef = Database.database().reference(withPath: "disconnectmessage");
// Write a string when this client loses connection
presenceRef.onDisconnectSetValue("I disconnected!")

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
FIRDatabaseReference *presenceRef = [[FIRDatabase database] referenceWithPath:@"disconnectmessage"];
// Write a string when this client loses connection
[presenceRef onDisconnectSetValue:@"I disconnected!"];

طريقة عمل ميزة on Connect

عند إنشاء عملية onDisconnect()، يتم على خادم قاعدة بيانات Firebase في الوقت الفعلي. يفحص الخادم الأمان وتتأكد من أن المستخدم يمكنه تنفيذ حدث الكتابة المطلوب، ويبلغ تطبيقك إذا كان غير صالح. ثم الخادم ويراقب الاتصال. إذا انتهت مهلة الاتصال في أي وقت أو بواسطة عميل قاعدة البيانات في الوقت الفعلي، فإن الخادم يفحص أمان مرة ثانية (للتأكد من أن العملية لا تزال صالحة) ثم يتم استدعاء الحدث.

يمكن لتطبيقك استخدام الاستدعاء في عملية الكتابة. للتأكّد من توصيل onDisconnect بشكل صحيح:

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
presenceRef.onDisconnectRemoveValue { error, reference in
  if let error = error {
    print("Could not establish onDisconnect event: \(error)")
  }
}

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
[presenceRef onDisconnectRemoveValueWithCompletionBlock:^(NSError *error, FIRDatabaseReference *reference) {
  if (error != nil) {
    NSLog(@"Could not establish onDisconnect event: %@", error);
  }
}];

يمكن أيضًا إلغاء حدث "onDisconnect" من خلال الاتصال بالرقم .cancel():

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
presenceRef.onDisconnectSetValue("I disconnected")
// some time later when we change our minds
presenceRef.cancelDisconnectOperations()

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
[presenceRef onDisconnectSetValue:@"I disconnected"];
// some time later when we change our minds
[presenceRef cancelDisconnectOperations];

اكتشاف حالة الاتصال

بالنسبة إلى العديد من الميزات المتعلّقة بالحضور، يكون ذلك مفيدًا لتطبيقك. لمعرفة ما إذا كان متصلاً بالإنترنت أو غير متصل بالإنترنت. قاعدة بيانات Firebase في الوقت الفعلي يوفر موقعًا خاصًا في /.info/connected يتم تعديل كل مرة يتم فيها تعديل حالة اتصال عميل قاعدة بيانات Firebase في الوقت الفعلي التغييرات. وفي ما يلي مثال لذلك:

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
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")
  }
})

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
FIRDatabaseReference *connectedRef = [[FIRDatabase database] referenceWithPath:@".info/connected"];
[connectedRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
  if([snapshot.value boolValue]) {
    NSLog(@"connected");
  } else {
    NSLog(@"not connected");
  }
}];

/.info/connected هي قيمة منطقية ليست متزامنة بين عملاء قاعدة البيانات في الوقت الفعلي لأن القيمة يعتمد على حالة العميل. بعبارة أخرى، إذا كان أحد العملاء تقرأ /.info/connected على أنها false، هذا لا ضمان قراءة عميل منفصل للخطأ أيضًا.

وقت الاستجابة

الطوابع الزمنية للخادم

وتوفر خوادم قاعدة بيانات Firebase في الوقت الفعلي آلية لإدراج الطوابع الزمنية التي تم إنشاؤها على الخادم كبيانات. وهذه الميزة بالإضافة إلى onDisconnect، طريقة سهلة لتدوين الملاحظات بشكل موثوق فيه الوقت الذي تم فيه قطع اتصال عميل قاعدة البيانات في الوقت الفعلي:

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
let userLastOnlineRef = Database.database().reference(withPath: "users/morgan/lastOnline")
userLastOnlineRef.onDisconnectSetValue(ServerValue.timestamp())

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
FIRDatabaseReference *userLastOnlineRef = [[FIRDatabase database] referenceWithPath:@"users/morgan/lastOnline"];
[userLastOnlineRef onDisconnectSetValue:[FIRServerValue timestamp]];

انحراف الساعة

في حين أن firebase.database.ServerValue.TIMESTAMP أكثر بكثير ودقيقة ومفضلة لمعظم عمليات القراءة/الكتابة، قد يكون من المفيد أحيانًا تقدير ساعة العميل فيما يتعلق بخوادم قاعدة بيانات Firebase في الوقت الفعلي. إِنْتَ يمكن إرفاق معاودة الاتصال بالموقع الجغرافي /.info/serverTimeOffset. وذلك من أجل الحصول على القيمة بالمللي ثانية التي يستخدمها عملاء قاعدة بيانات Firebase في الوقت الفعلي تضيفه إلى الوقت المحلي المبلّغ عنه (وقت الحقبة بالمللي ثانية) لتقدير وقت الخادم. لاحظ أن دقة هذه الإزاحة يمكن أن تتأثر وقت استجابة الشبكة، لذا فهي مفيدة في المقام الأول لاكتشاف اختلافات كبيرة (أكبر من ثانية واحدة) في وقت الساعة.

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
let offsetRef = Database.database().reference(withPath: ".info/serverTimeOffset")
offsetRef.observe(.value, with: { snapshot in
  if let offset = snapshot.value as? TimeInterval {
    print("Estimated server time in milliseconds: \(Date().timeIntervalSince1970 * 1000 + offset)")
  }
})

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
FIRDatabaseReference *offsetRef = [[FIRDatabase database] referenceWithPath:@".info/serverTimeOffset"];
[offsetRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
  NSTimeInterval offset = [(NSNumber *)snapshot.value doubleValue];
  NSTimeInterval estimatedServerTimeMs = [[NSDate date] timeIntervalSince1970] * 1000.0 + offset;
  NSLog(@"Estimated server time: %0.3f", estimatedServerTimeMs);
}];

نموذج تطبيق التواجد

من خلال الجمع بين عمليات قطع الاتصال ومراقبة حالة الاتصال الطوابع الزمنية للخادم، فيمكنك إنشاء نظام تواجد المستخدم. في هذا النظام، يقوم كل مستخدم بتخزين البيانات في موقع قاعدة البيانات للإشارة إلى ما إذا كان برنامج قاعدة البيانات في الوقت الفعلي متصل بالإنترنت. يضبط العملاء هذا الموقع على "صحيح" عندما عند اتصالهم بالإنترنت وبطابع زمني عند قطع الاتصال. هذا الطابع الزمني تشير إلى آخر مرة كان فيها المستخدم المحدد متصلاً بالإنترنت.

تجدر الإشارة إلى أنّ تطبيقك يجب أن يضع عمليات إلغاء الربط في قائمة انتظار قبل أن يبدأ المستخدم وتمييزها عبر الإنترنت، لتجنب أي شروط سباق في حال انعقاد يتم فقدان اتصال الشبكة قبل إرسال كلا الأمرين إلى الخادم.

إليك نظام بسيط لتواجد المستخدم:

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
// since I can connect from multiple devices, we store each connection instance separately
// any time that connectionsRef's value is null (i.e. has no children) I am offline
let myConnectionsRef = Database.database().reference(withPath: "users/morgan/connections")

// stores the timestamp of my last disconnect (the last time I was seen online)
let lastOnlineRef = Database.database().reference(withPath: "users/morgan/lastOnline")

let connectedRef = Database.database().reference(withPath: ".info/connected")

connectedRef.observe(.value, with: { snapshot in
  // only handle connection established (or I've reconnected after a loss of connection)
  guard snapshot.value as? Bool ?? false else { return }

  // add this device to my connections list
  let con = myConnectionsRef.childByAutoId()

  // when this device disconnects, remove it.
  con.onDisconnectRemoveValue()

  // The onDisconnect() call is before the call to set() itself. This is to avoid a race condition
  // where you set the user's presence to true and the client disconnects before the
  // onDisconnect() operation takes effect, leaving a ghost user.

  // this value could contain info about the device or a timestamp instead of just true
  con.setValue(true)

  // when I disconnect, update the last time I was seen online
  lastOnlineRef.onDisconnectSetValue(ServerValue.timestamp())
})

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
// since I can connect from multiple devices, we store each connection instance separately
// any time that connectionsRef's value is null (i.e. has no children) I am offline
FIRDatabaseReference *myConnectionsRef = [[FIRDatabase database] referenceWithPath:@"users/morgan/connections"];

// stores the timestamp of my last disconnect (the last time I was seen online)
FIRDatabaseReference *lastOnlineRef = [[FIRDatabase database] referenceWithPath:@"users/morgan/lastOnline"];

FIRDatabaseReference *connectedRef = [[FIRDatabase database] referenceWithPath:@".info/connected"];
[connectedRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
  if([snapshot.value boolValue]) {
    // connection established (or I've reconnected after a loss of connection)

    // add this device to my connections list
    FIRDatabaseReference *con = [myConnectionsRef childByAutoId];

    // when this device disconnects, remove it
    [con onDisconnectRemoveValue];

    // The onDisconnect() call is before the call to set() itself. This is to avoid a race condition
    // where you set the user's presence to true and the client disconnects before the
    // onDisconnect() operation takes effect, leaving a ghost user.

    // this value could contain info about the device or a timestamp instead of just true
    [con setValue:@YES];


    // when I disconnect, update the last time I was seen online
    [lastOnlineRef onDisconnectSetValue:[FIRServerValue timestamp]];
  }
}];