با لیست داده ها در پلتفرم های اپل کار کنید

دریافت یک مرجع پایگاه داده FIR

برای خواندن یا نوشتن داده‌ها از پایگاه داده، به یک نمونه از FIRDatabaseReference نیاز دارید:

سویفت

توجه: این محصول Firebase در App Clip target در دسترس نیست.
var ref: DatabaseReference!

ref = Database.database().reference()

هدف-سی

توجه: این محصول Firebase در App Clip target در دسترس نیست.
@property (strong, nonatomic) FIRDatabaseReference *ref;

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

فهرست‌های خواندن و نوشتن

به لیستی از داده‌ها اضافه کنید

از متد childByAutoId برای افزودن داده‌ها به یک لیست در برنامه‌های چندکاربره استفاده کنید. متد childByAutoId هر بار که یک فرزند جدید به مرجع Firebase مشخص شده اضافه می‌شود، یک کلید منحصر به فرد تولید می‌کند. با استفاده از این کلیدهای تولید شده خودکار برای هر عنصر جدید در لیست، چندین کلاینت می‌توانند فرزندان را همزمان و بدون تداخل در نوشتن، به یک مکان اضافه کنند. کلید منحصر به فرد تولید شده توسط childByAutoId بر اساس یک مهر زمانی است، بنابراین موارد لیست به طور خودکار به ترتیب زمانی مرتب می‌شوند.

شما می‌توانید از ارجاع به داده‌های جدید برگردانده شده توسط متد childByAutoId برای دریافت مقدار کلید تولید شده خودکار فرزند یا تنظیم داده‌ها برای فرزند استفاده کنید. فراخوانی getKey روی یک ارجاع childByAutoId کلید تولید شده خودکار را برمی‌گرداند.

شما می‌توانید از این کلیدهای تولید شده خودکار برای ساده‌سازی مسطح‌سازی ساختار داده خود استفاده کنید. برای اطلاعات بیشتر، به مثال خروجی داده‌ها مراجعه کنید.

به رویدادهای فرزند گوش دهید

رویدادهای فرزند در پاسخ به عملیات خاصی که برای فرزندان یک گره از عملیاتی مانند اضافه شدن یک فرزند جدید از طریق متد childByAutoId یا به‌روزرسانی یک فرزند از طریق متد updateChildValues ​​رخ می‌دهد، فعال می‌شوند.

نوع رویداد کاربرد معمول
FIRDataEventTypeChildAdded بازیابی لیست آیتم‌ها یا گوش دادن به موارد اضافه شده به لیست آیتم‌ها. این رویداد یک بار برای هر فرزند موجود و سپس هر بار که فرزند جدیدی به مسیر مشخص شده اضافه می‌شود، فعال می‌شود. به شنونده یک snapshot حاوی داده‌های فرزند جدید ارسال می‌شود.
FIRDataEventTypeChildChanged به تغییرات در موارد موجود در یک لیست گوش دهید. این رویداد هر زمان که یک گره فرزند تغییر کند، فعال می‌شود. این شامل هرگونه تغییر در فرزندان گره فرزند نیز می‌شود. تصویر لحظه‌ای ارسال شده به شنونده رویداد، حاوی داده‌های به‌روزرسانی شده برای فرزند است.
FIRDataEventTypeChildRemoved به حذف شدن آیتم‌ها از یک لیست گوش دهید. این رویداد زمانی فعال می‌شود که یک فرزند فوری حذف شود. تصویر لحظه‌ای ارسال شده به بلوک فراخوانی شامل داده‌های فرزند حذف شده است.
FIRDataEventTypeChildMoved به تغییرات در ترتیب آیتم‌ها در یک لیست مرتب گوش دهید. این رویداد هر زمان که یک به‌روزرسانی باعث تغییر ترتیب فرزند شود، آغاز می‌شود. این رویداد با داده‌هایی که توسط queryOrderedByChild یا queryOrderedByValue مرتب شده‌اند، استفاده می‌شود.

هر یک از این روش‌ها در کنار هم می‌توانند برای گوش دادن به تغییرات یک گره خاص در پایگاه داده مفید باشند. به عنوان مثال، یک برنامه وبلاگ نویسی اجتماعی ممکن است از این روش‌ها با هم برای نظارت بر فعالیت در نظرات یک پست استفاده کند، همانطور که در زیر نشان داده شده است:

سویفت

توجه: این محصول Firebase در App Clip target در دسترس نیست.
// 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
  )
})

هدف-سی

توجه: این محصول Firebase در App Clip target در دسترس نیست.
// 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 به لیستی از داده‌ها، کل لیست داده‌ها را به عنوان یک DataSnapshot واحد برمی‌گرداند، که می‌توانید برای دسترسی به تک تک فرزندان، آن را پیمایش کنید.

حتی وقتی فقط یک مورد منطبق برای کوئری وجود دارد، snapshot هنوز یک لیست است؛ فقط شامل یک مورد است. برای دسترسی به مورد، باید روی نتیجه حلقه بزنید:

سویفت

توجه: این محصول Firebase در App Clip target در دسترس نیست.
_commentsRef.observe(.value) { snapshot in
  for child in snapshot.children {
    ...
  }
}

هدف-سی

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

این الگو می‌تواند زمانی مفید باشد که می‌خواهید همه فرزندان یک لیست را در یک عملیات واحد دریافت کنید، به جای اینکه منتظر رویدادهای اضافه شدن فرزند اضافی باشید.

مرتب‌سازی و فیلتر کردن داده‌ها

شما می‌توانید از کلاس Realtime Database FIRDatabaseQuery برای بازیابی داده‌های مرتب‌شده بر اساس کلید، مقدار یا مقدار یک فرزند استفاده کنید. همچنین می‌توانید نتیجه مرتب‌شده را به تعداد مشخصی از نتایج یا طیف وسیعی از کلیدها یا مقادیر فیلتر کنید.

مرتب‌سازی داده‌ها

برای بازیابی داده‌های مرتب‌شده، با مشخص کردن یکی از روش‌های order-by برای تعیین نحوه‌ی مرتب‌سازی نتایج شروع کنید:

روش کاربرد
queryOrderedByKey نتایج را بر اساس کلیدهای فرزند مرتب کنید.
queryOrderedByValue نتایج را بر اساس مقادیر فرزند مرتب کنید.
queryOrderedByChild نتایج را بر اساس مقدار یک کلید فرزند مشخص شده یا مسیر فرزند تو در تو مرتب می‌کند.

شما فقط می‌توانید از یک متد order-by در یک زمان استفاده کنید. فراخوانی چندین باره‌ی یک متد order-by در یک query باعث ایجاد خطا می‌شود.

مثال زیر نشان می‌دهد که چگونه می‌توانید لیستی از برترین پست‌های یک کاربر را که بر اساس تعداد ستاره‌هایش مرتب شده‌اند، بازیابی کنید:

سویفت

توجه: این محصول Firebase در App Clip target در دسترس نیست.
// My top posts by number of stars
let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")

هدف-سی

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

این کوئری پست‌های کاربر را از مسیر موجود در پایگاه داده بر اساس شناسه کاربری آنها، که بر اساس تعداد ستاره‌هایی که هر پست دریافت کرده است، مرتب شده است، بازیابی می‌کند. این تکنیک استفاده از شناسه‌ها به عنوان کلیدهای اندیس، data fan out نامیده می‌شود، می‌توانید اطلاعات بیشتر در مورد آن را در Structure Your Database بخوانید.

فراخوانی متد queryOrderedByChild کلید فرزند را برای مرتب‌سازی نتایج بر اساس آن مشخص می‌کند. در این مثال، پست‌ها بر اساس مقدار فرزند "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 انجام می‌شود.

سویفت

توجه: این محصول Firebase در App Clip target در دسترس نیست.
 
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")

هدف-سی

توجه: این محصول Firebase در App Clip target در دسترس نیست.
 
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];

برای اطلاعات بیشتر در مورد نحوه مرتب‌سازی انواع داده‌های دیگر، به نحوه مرتب‌سازی داده‌های پرس‌وجو مراجعه کنید.

فیلتر کردن داده‌ها

برای فیلتر کردن داده‌ها، می‌توانید هنگام ساخت یک پرس‌وجو، هر یک از روش‌های محدودیت یا محدوده را با یک روش مرتب‌سازی ترکیب کنید.

روش کاربرد
queryLimitedToFirst حداکثر تعداد اقلامی را که از ابتدای لیست مرتب‌شده‌ی نتایج برگردانده می‌شوند، تنظیم می‌کند.
queryLimitedToLast حداکثر تعداد اقلامی را که از انتهای لیست مرتب‌شده‌ی نتایج برگردانده می‌شوند، تنظیم می‌کند.
queryStartingAtValue بسته به روش مرتب‌سازی انتخاب‌شده، اقلامی را که بزرگتر یا مساوی کلید یا مقدار مشخص‌شده هستند، برمی‌گرداند.
queryStartingAfterValue بسته به روش مرتب‌سازی انتخاب‌شده، اقلامی را که بزرگتر از کلید یا مقدار مشخص‌شده هستند، برمی‌گرداند.
queryEndingAtValue بسته به روش مرتب‌سازی انتخاب‌شده، اقلام کوچکتر یا مساوی با کلید یا مقدار مشخص‌شده را برمی‌گرداند.
queryEndingBeforeValue بسته به روش مرتب‌سازی انتخاب‌شده، اقلامی را که کمتر از کلید یا مقدار مشخص‌شده هستند، برمی‌گرداند.
queryEqualToValue بسته به روش مرتب‌سازی انتخاب‌شده، اقلامی را که برابر با کلید یا مقدار مشخص‌شده هستند، برمی‌گرداند.

برخلاف متدهای مرتب‌سازی بر اساس، می‌توانید چندین تابع محدودکننده یا محدوده‌ای را با هم ترکیب کنید. برای مثال، می‌توانید متدهای queryStartingAtValue و queryEndingAtValue را برای محدود کردن نتایج به یک محدوده مشخص از مقادیر ترکیب کنید.

محدود کردن تعداد نتایج

شما می‌توانید از متدهای queryLimitedToFirst و queryLimitedToLast برای تعیین حداکثر تعداد فرزندانی که باید برای یک فراخوانی مجدد مشخص همگام‌سازی شوند، استفاده کنید. برای مثال، اگر از queryLimitedToFirst برای تعیین محدودیت ۱۰۰ استفاده کنید، در ابتدا فقط تا ۱۰۰ فراخوانی مجدد FIRDataEventTypeChildAdded دریافت خواهید کرد. اگر کمتر از ۱۰۰ مورد در پایگاه داده Firebase خود ذخیره کرده‌اید، یک فراخوانی مجدد FIRDataEventTypeChildAdded برای هر مورد فعال می‌شود.

با تغییر آیتم‌ها، برای آیتم‌هایی که وارد کوئری می‌شوند، فراخوانی‌های FIRDataEventTypeChildAdded و برای آیتم‌هایی که از آن حذف می‌شوند، فراخوانی‌های FIRDataEventTypeChildRemoved دریافت می‌کنید تا تعداد کل روی ۱۰۰ باقی بماند.

مثال زیر نشان می‌دهد که چگونه یک برنامه وبلاگ‌نویسی نمونه می‌تواند فهرستی از ۱۰۰ پست اخیر همه کاربران را بازیابی کند:

سویفت

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

هدف-سی

توجه: این محصول Firebase در App Clip target در دسترس نیست.
// 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 برای انتخاب نقاط شروع، پایان و هم‌ارزی دلخواه برای پرس‌وجوها استفاده کنید. این می‌تواند برای صفحه‌بندی داده‌ها یا یافتن مواردی با فرزندانی که مقدار خاصی دارند مفید باشد.

نحوه مرتب سازی داده های پرس و جو

این بخش نحوه مرتب‌سازی داده‌ها بر اساس هر یک از متدهای order-by در کلاس FIRDatabaseQuery را توضیح می‌دهد.

queryOrderedByKey

هنگام استفاده از queryOrderedByKey برای مرتب‌سازی داده‌ها، داده‌ها بر اساس کلید به صورت صعودی مرتب می‌شوند.

  1. فرزندانی که کلیدی دارند که می‌تواند به عنوان یک عدد صحیح ۳۲ بیتی تجزیه شود، ابتدا به صورت صعودی مرتب می‌شوند.
  2. فرزندانی که کلیدشان یک مقدار رشته‌ای است، در مرحله‌ی بعد قرار می‌گیرند و به صورت لغوی و به ترتیب صعودی مرتب شده‌اند.

queryOrderedByValue

هنگام استفاده از queryOrderedByValue ، فرزندان بر اساس مقدارشان مرتب می‌شوند. معیارهای مرتب‌سازی مشابه queryOrderedByChild هستند، با این تفاوت که به جای مقدار یک کلید فرزند مشخص، از مقدار گره استفاده می‌شود.

queryOrderedByChild

هنگام استفاده از queryOrderedByChild ، داده‌هایی که حاوی کلید فرزند مشخص شده هستند به صورت زیر مرتب می‌شوند:

  1. فرزندانی که مقدارشان برای کلید فرزند مشخص شده nil است، در اولویت قرار می‌گیرند.
  2. فرزندانی که مقدار false برای کلید فرزند مشخص شده دارند، در مرحله بعد قرار می‌گیرند. اگر چندین فرزند مقدار false داشته باشند، بر اساس کلید به صورت لغوی مرتب می‌شوند.
  3. فرزندانی که مقدار true برای کلید فرزند مشخص شده دارند، در مرحله بعد قرار می‌گیرند. اگر چندین فرزند مقدار true داشته باشند، بر اساس کلید به صورت لغوی مرتب می‌شوند.
  4. فرزندانی که مقدار عددی دارند، در مرحله بعد قرار می‌گیرند و به ترتیب صعودی مرتب می‌شوند. اگر چندین فرزند برای گره فرزند مشخص شده، مقدار عددی یکسانی داشته باشند، بر اساس کلید مرتب می‌شوند.
  5. رشته‌ها بعد از اعداد می‌آیند و به صورت لغوی و به ترتیب صعودی مرتب می‌شوند. اگر چندین فرزند برای گره فرزند مشخص شده مقدار یکسانی داشته باشند، بر اساس کلید به صورت لغوی مرتب می‌شوند.
  6. اشیاء در آخر می‌آیند و از نظر لغوی بر اساس کلید به ترتیب صعودی مرتب می‌شوند.

جدا کردن شنوندگان

ناظرها (Observer) هنگام خروج شما ViewController ، همگام‌سازی داده‌ها را به‌طور خودکار متوقف نمی‌کنند. اگر یک ناظر (Observer) به درستی حذف نشود، همچنان به همگام‌سازی داده‌ها با حافظه محلی ادامه می‌دهد و هر شیء ثبت‌شده در closure مربوط به کنترل‌کننده رویداد (event handler) را حفظ خواهد کرد، که می‌تواند باعث نشت حافظه (memory leaks) شود. هنگامی که دیگر به یک ناظر نیازی نیست، آن را با ارسال FIRDatabaseHandle مرتبط به متد removeObserverWithHandle حذف کنید.

وقتی یک بلوک فراخوانی (callback block) به یک مرجع (reference) اضافه می‌کنید، یک FIRDatabaseHandle برگردانده می‌شود. از این دستگیره‌ها می‌توان برای حذف بلوک فراخوانی استفاده کرد.

اگر چندین شنونده به یک ارجاع پایگاه داده اضافه شده باشد، هر شنونده هنگام وقوع یک رویداد فراخوانی می‌شود. برای متوقف کردن همگام‌سازی داده‌ها در آن مکان، باید با فراخوانی متد removeAllObservers ، تمام ناظران (Observers) را در آن مکان حذف کنید.

فراخوانی removeObserverWithHandle یا removeAllObservers روی یک شنونده، شنونده‌های ثبت‌شده روی گره‌های فرزند آن را به‌طور خودکار حذف نمی‌کند؛ شما همچنین باید آن ارجاع‌ها یا دستگیره‌ها را برای حذف آنها پیگیری کنید.

مراحل بعدی