العمل باستخدام قوائم البيانات على منصات Apple

الحصول على FIRDatabaseReference

لقراءة البيانات من قاعدة البيانات أو كتابتها، تحتاج إلى مثيل من FIRDatabaseReference:

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
var ref: DatabaseReference!

ref = Database.database().reference()

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
@property (strong, nonatomic) FIRDatabaseReference *ref;

self.ref = [[FIRDatabase database] reference];

قراءة القوائم وكتابتها

الإلحاق بقائمة بيانات

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

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

يمكنك استخدام هذه المفاتيح التي يتم إنشاؤها تلقائيًا لتبسيط عملية تسوية بنية البيانات. لمزيد من المعلومات، يُرجى الاطّلاع على مثال على تكرار البيانات.

الاستماع إلى الأحداث الفرعية

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

نوع الحدث الاستخدام المعتاد
FIRDataEventTypeChildAdded استرداد قوائم العناصر أو الاستماع إلى الإضافات إلى قائمة العناصر يتم تشغيل هذا الحدث مرة واحدة لكل عنصر فرعي حالي ثم مرة أخرى في كل مرة تتم فيها إضافة عنصر فرعي جديد إلى المسار المحدد. يتم تمرير لقطة تحتوي على بيانات الطفل الجديد إلى المستمع.
FIRDataEventTypeChildChanged الاستماع إلى التغييرات التي تطرأ على العناصر في قائمة يتم تشغيل هذا الحدث في أي وقت يتم فيه تعديل عقدة فرعية. ويشمل ذلك أي تعديلات على العناصر التابعة للعقدة الفرعية. تحتوي اللقطة التي تم تمريرها إلى متتبِّع الأحداث على البيانات المعدَّلة للطفل.
FIRDataEventTypeChildRemoved الاستماع إلى العناصر التي تتم إزالتها من القائمة يتم تشغيل هذا الحدث عند إزالة عنصر فرعي مباشر.تحتوي اللقطة التي تم تمريرها إلى كتلة رد الاتصال على بيانات العنصر الفرعي الذي تمت إزالته.
FIRDataEventTypeChildMoved الاستماع إلى التغييرات في ترتيب العناصر في قائمة مع ترتيب يتم بدء هذا الحدث عندما يؤدي تحديث إلى إعادة ترتيب الحدث الفرعي. ويتم استخدامها مع البيانات التي يتم ترتيبها حسب queryOrderedByChild أو queryOrderedByValue.

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

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
// Listen for new comments in the Firebase database
commentsRef.observe(.childAdded, with: { (snapshot) -> Void in
  self.comments.append(snapshot)
  self.tableView.insertRows(
    at: [IndexPath(row: self.comments.count - 1, section: self.kSectionComments)],
    with: UITableView.RowAnimation.automatic
  )
})
// Listen for deleted comments in the Firebase database
commentsRef.observe(.childRemoved, with: { (snapshot) -> Void in
  let index = self.indexOfMessage(snapshot)
  self.comments.remove(at: index)
  self.tableView.deleteRows(
    at: [IndexPath(row: index, section: self.kSectionComments)],
    with: UITableView.RowAnimation.automatic
  )
})

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
// Listen for new comments in the Firebase database
[_commentsRef
              observeEventType:FIRDataEventTypeChildAdded
              withBlock:^(FIRDataSnapshot *snapshot) {
                [self.comments addObject:snapshot];
                [self.tableView insertRowsAtIndexPaths:@[
                  [NSIndexPath indexPathForRow:self.comments.count - 1 inSection:kSectionComments]
                ]
                                      withRowAnimation:UITableViewRowAnimationAutomatic];
              }];
// Listen for deleted comments in the Firebase database
[_commentsRef
 observeEventType:FIRDataEventTypeChildRemoved
 withBlock:^(FIRDataSnapshot *snapshot) {
   int index = [self indexOfMessage:snapshot];
   [self.comments removeObjectAtIndex:index];
   [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:kSectionComments]]
                         withRowAnimation:UITableViewRowAnimationAutomatic];
 }];

الاستماع إلى أحداث القيمة

على الرغم من أنّ الاستماع إلى الأحداث الفرعية هو الطريقة المقترَحة لقراءة قوائم البيانات، هناك حالات يكون فيها الاستماع إلى أحداث القيمة في مرجع قائمة مفيدًا.

سيؤدي إرفاق مراقب FIRDataEventTypeValue بقائمة بيانات إلى عرض قائمة البيانات بالكامل كلقطة بيانات واحدة، والتي يمكنك بعد ذلك تكرارها للوصول إلى العناصر الفرعية الفردية.

حتى عندما يكون هناك تطابق واحد فقط لطلب البحث، تظل اللقطة قائمة، ولكنها تحتوي على عنصر واحد فقط. للوصول إلى العنصر، تحتاج إلى تكرار النتيجة:

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
_commentsRef.observe(.value) { snapshot in
  for child in snapshot.children {
    ...
  }
}

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
[_commentsRef
              observeEventType:FIRDataEventTypeValue
              withBlock:^(FIRDataSnapshot *snapshot) {
                // Loop over children
                NSEnumerator *children = [snapshot children];
                FIRDataSnapshot *child;
                while (child = [children nextObject]) {
                  // ...
                }
              }];

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

فرز البيانات وتصفيتها

يمكنك استخدام فئة Realtime Database FIRDatabaseQuery لاسترداد البيانات التي تم ترتيبها حسب المفتاح أو القيمة أو قيمة العنصر الثانوي. يمكنك أيضًا فلترة النتيجة التي تم ترتيبها إلى عدد معيّن من النتائج أو نطاق من المفاتيح أو القيم.

ترتيب البيانات

لاسترداد البيانات التي تم ترتيبها، ابدأ بتحديد إحدى طرق الترتيب لتحديد كيفية ترتيب النتائج:

الطريقة الاستخدام
queryOrderedByKey ترتيب النتائج حسب المفاتيح الفرعية
queryOrderedByValue ترتيب النتائج حسب القيم الفرعية
queryOrderedByChild يمكنك ترتيب النتائج حسب قيمة مفتاح فرعي محدّد أو مسار فرعي مدمج.

يمكنك استخدام طريقة ترتيب واحدة فقط في كل مرة. يؤدي استدعاء طريقة الترتيب عدة مرات في طلب البحث نفسه إلى ظهور خطأ.

يوضّح المثال التالي كيفية استرداد قائمة بأهم منشورات المستخدم مرتّبة حسب عدد النجوم:

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
// My top posts by number of stars
let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
// My top posts by number of stars
FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"]
                                      child:[super getUid]]
                                     queryOrderedByChild:@"starCount"];

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

The call to the queryOrderedByChild method specifies the child key to order the results by. في هذا المثال، يتم ترتيب المشاركات حسب قيمة الفرع "starCount" في كل مشاركة. يمكن أيضًا ترتيب طلبات البحث حسب العناصر الفرعية المتداخلة، في حال كانت لديك بيانات تبدو على النحو التالي:

"posts": {
  "ts-functions": {
    "metrics": {
      "views" : 1200000,
      "likes" : 251000,
      "shares": 1200,
    },
    "title" : "Why you should use TypeScript for writing Cloud Functions",
    "author": "Doug",
  },
  "android-arch-3": {
    "metrics": {
      "views" : 900000,
      "likes" : 117000,
      "shares": 144,
    },
    "title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
    "author": "Doug",
  }
},

في هذه الحالة، يمكننا ترتيب عناصر القائمة حسب القيم المدمجة ضمن المفتاح metrics من خلال تحديد المسار النسبي للعنصر الثانوي المدمج في طلب queryOrderedByChild.

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
 
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
 
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];

لمزيد من المعلومات حول كيفية ترتيب أنواع البيانات الأخرى، يُرجى الاطّلاع على كيفية ترتيب بيانات طلبات البحث.

تصفية البيانات

لفلترة البيانات، يمكنك دمج أي من طرق الحد أو النطاق مع طريقة الترتيب عند إنشاء طلب بحث.

الطريقة الاستخدام
queryLimitedToFirst تحدّد هذه المَعلمة الحد الأقصى لعدد العناصر التي سيتم عرضها من بداية قائمة النتائج المرتبة.
queryLimitedToLast تحدّد هذه المَعلمة الحد الأقصى لعدد العناصر التي يتم عرضها من نهاية قائمة النتائج المرتبة.
queryStartingAtValue عرض العناصر الأكبر من أو تساوي المفتاح أو القيمة المحدّدة، استنادًا إلى طريقة الترتيب التي تم اختيارها
queryStartingAfterValue عرض العناصر الأكبر من المفتاح أو القيمة المحدّدة، استنادًا إلى طريقة الترتيب التي تم اختيارها
queryEndingAtValue عرض العناصر التي تكون أقل من أو تساوي المفتاح أو القيمة المحدّدة، استنادًا إلى طريقة الترتيب التي تم اختيارها
queryEndingBeforeValue عرض العناصر التي تكون أقل من المفتاح أو القيمة المحدّدة، استنادًا إلى طريقة الترتيب التي تم اختيارها.
queryEqualToValue عرض العناصر التي تساوي المفتاح أو القيمة المحدّدة، استنادًا إلى طريقة الترتيب التي تم اختيارها

على عكس طرق الترتيب، يمكنك الجمع بين عدة دوال للحدّ أو النطاق. على سبيل المثال، يمكنك الجمع بين الطريقتين queryStartingAtValue وqueryEndingAtValue لحصر النتائج في نطاق محدّد من القيم.

تحديد عدد النتائج

يمكنك استخدام الطريقتَين queryLimitedToFirst وqueryLimitedToLast لضبط الحد الأقصى لعدد العناصر الفرعية التي تتم مزامنتها لردّ اتصال معيّن. على سبيل المثال، إذا كنت تستخدم queryLimitedToFirst لضبط حدّ أقصى يبلغ 100، لن تتلقّى في البداية سوى ما يصل إلى 100 طلب معاودة اتصال من FIRDataEventTypeChildAdded. إذا كان لديك أقل من 100 عنصر مخزّن في قاعدة بيانات Firebase، يتم تنشيط دالة رد اتصال FIRDataEventTypeChildAdded لكل عنصر.

عندما تتغيّر العناصر، ستتلقّى عمليات استدعاء FIRDataEventTypeChildAdded للعناصر التي تدخل في طلب البحث وعمليات استدعاء FIRDataEventTypeChildRemoved للعناصر التي تخرج منه، ليبقى إجمالي العدد 100.

يوضح المثال التالي كيف يمكن لتطبيق تدوين نموذجي استرداد قائمة بأحدث 100 منشور لجميع المستخدمين:

Swift

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!

Objective-C

ملاحظة: لا يتوفّر منتج Firebase هذا في هدف App Clip.
// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];

الفلترة حسب المفتاح أو القيمة

يمكنك استخدام queryStartingAtValue وqueryStartingAfterValue وqueryEndingAtValue وqueryEndingBeforeValue وqueryEqualToValue لاختيار نقاط بداية ونهاية وتكافؤ عشوائية لطلبات البحث. يمكن أن يكون ذلك مفيدًا لتقسيم البيانات إلى صفحات أو العثور على عناصر فرعية لها قيمة معيّنة.

كيفية ترتيب بيانات طلب البحث

يوضّح هذا القسم كيفية ترتيب البيانات حسب كل طريقة من طرق الترتيب في فئة FIRDatabaseQuery.

queryOrderedByKey

عند استخدام queryOrderedByKey لترتيب بياناتك، يتم عرض البيانات بترتيب تصاعدي حسب المفتاح.

  1. تظهر أولاً العناصر الفرعية التي تحتوي على مفتاح يمكن تحليله كعدد صحيح مكوّن من 32 بت، ويتم ترتيبها تصاعديًا.
  2. بعد ذلك، يتم ترتيب العناصر الثانوية التي تحتوي على قيمة سلسلة كمفتاح لها، ويتم ترتيبها معجميًا تصاعديًا.

queryOrderedByValue

عند استخدام queryOrderedByValue، يتم ترتيب العناصر الفرعية حسب قيمتها. معايير الترتيب هي نفسها في queryOrderedByChild، باستثناء أنّه يتم استخدام قيمة العقدة بدلاً من قيمة مفتاح فرعي محدّد.

queryOrderedByChild

عند استخدام queryOrderedByChild، يتم ترتيب البيانات التي تحتوي على المفتاح الفرعي المحدد على النحو التالي:

  1. تظهر أولاً العناصر الفرعية التي لها قيمة nil لمفتاح الطفل المحدّد.
  2. تأتي بعد ذلك العناصر الثانوية التي لها القيمة false للمفتاح الثانوي المحدّد. إذا كان لدى عدة عناصر فرعية قيمة false، يتم ترتيبها معجميًا حسب المفتاح.
  3. تأتي بعد ذلك العناصر الثانوية التي لها القيمة true للمفتاح الثانوي المحدّد. إذا كان لدى عدة عناصر فرعية قيمة true، يتم ترتيبها معجميًا حسب المفتاح.
  4. تأتي بعد ذلك العناصر الثانوية التي لها قيمة رقمية، ويتم ترتيبها تصاعديًا. إذا كان هناك عدة عناصر فرعية لها القيمة الرقمية نفسها للعقدة الفرعية المحددة، يتم ترتيبها حسب المفتاح.
  5. تأتي السلاسل بعد الأرقام ويتم ترتيبها معجميًا بترتيب تصاعدي. إذا كان لدى عدة عناصر فرعية القيمة نفسها للعقدة الفرعية المحددة، يتم ترتيبها معجميًا حسب المفتاح.
  6. تأتي العناصر في النهاية ويتم ترتيبها معجميًا حسب المفتاح بترتيب تصاعدي.

فصل المستمعين

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

عند إضافة مجموعة ردّ اتصال إلى مرجع، يتم عرض FIRDatabaseHandle. يمكن استخدام هذه المقابض لإزالة مجموعة عمليات الاستدعاء.

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

لا يؤدي استدعاء removeObserverWithHandle أو removeAllObservers على مستمع إلى إزالة المستمعين المسجلين على العُقد الفرعية تلقائيًا، بل يجب أيضًا تتبُّع هذه المراجع أو المعالجات لإزالتها.

الخطوات التالية