קבלת FIRDatabaseReference
כדי לקרוא נתונים ממסד הנתונים או לכתוב אליו, צריך מופע של FIRDatabaseReference:
Swift
var ref: DatabaseReference! ref = Database.database().reference()
Objective-C
@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];
רשימות קריאה וכתיבה
הוספה לרשימת נתונים
משתמשים ב-method childByAutoId כדי להוסיף נתונים לרשימה באפליקציות עם כמה משתמשים. השיטה childByAutoId יוצרת מפתח ייחודי בכל פעם שנוסף צאצא חדש להפניה שצוינה ב-Firebase. כשמשתמשים במפתחות שנוצרים אוטומטית לכל רכיב חדש ברשימה, כמה לקוחות יכולים להוסיף צאצאים לאותו מיקום בו-זמנית בלי התנגשויות כתיבה. המפתח הייחודי שנוצר על ידי childByAutoId מבוסס על חותמת זמן, כך שהפריטים ברשימה מסודרים באופן אוטומטי בסדר כרונולוגי.
אתם יכולים להשתמש בהפניה לנתונים החדשים שהוחזרו על ידי השיטה childByAutoId כדי לקבל את הערך של המפתח שנוצר באופן אוטומטי של הצאצא או להגדיר נתונים לצאצא.
קריאה ל-getKey בהפניה ל-childByAutoId מחזירה את המפתח שנוצר אוטומטית.
אתם יכולים להשתמש במפתחות שנוצרו באופן אוטומטי כדי לפשט את מבנה הנתונים. למידע נוסף, ראו דוגמה להסתעפות נתונים.
האזנה לאירועים משניים
אירועים משניים מופעלים בתגובה לפעולות ספציפיות שמתרחשות בצאצאים של צומת, כמו הוספת צאצא חדש באמצעות השיטה childByAutoId או עדכון של צאצא באמצעות השיטה updateChildValues.
| סוג האירוע | שימוש אופייני |
|---|---|
FIRDataEventTypeChildAdded |
אחזור רשימות של פריטים או האזנה לתוספות לרשימת פריטים. האירוע הזה מופעל פעם אחת לכל צאצא קיים, ואז שוב בכל פעם שנוסף צאצא חדש לנתיב שצוין. המאזין מקבל תמונת מצב שמכילה את הנתונים של הצאצא החדש. |
FIRDataEventTypeChildChanged |
האזנה לשינויים בפריטים ברשימה. האירוע הזה מופעל בכל פעם שצומת צאצא משתנה. זה כולל כל שינוי בצאצאים של צומת הצאצא. תמונת המצב שמועברת לרכיב event listener מכילה את הנתונים המעודכנים של הצאצא. |
FIRDataEventTypeChildRemoved |
האזנה לפריטים שמוסרים מרשימה. האירוע הזה מופעל כשמסירים צאצא מיידי.קובץ ה-snapshot שמועבר לבלוק הקריאה החוזרת מכיל את הנתונים של הצאצא שהוסר. |
FIRDataEventTypeChildMoved |
האזנה לשינויים בסדר הפריטים ברשימה ממוינת.
האירוע הזה מופעל בכל פעם שעדכון גורם לשינוי הסדר של הצאצא. הוא משמש עם נתונים שמסודרים לפי queryOrderedByChild
או queryOrderedByValue.
|
השילוב של כל אלה יכול להיות שימושי להאזנה לשינויים בצומת ספציפי במסד נתונים. לדוגמה, אפליקציה של בלוג חברתי יכולה להשתמש בשיטות האלה ביחד כדי לעקוב אחרי הפעילות בתגובות של פוסט, כמו שמוצג בהמשך:
Swift
// 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
// 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 יחיד, שאפשר לעבור עליו בלולאה כדי לגשת לצאצאים ספציפיים.
גם אם יש רק התאמה אחת לשאילתה, תמונת המצב עדיין תהיה רשימה, אבל היא תכיל רק פריט אחד. כדי לגשת לפריט, צריך לעבור על התוצאה בלולאה:
Swift
_commentsRef.observe(.value) { snapshot in for child in snapshot.children { ... } }
Objective-C
[_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
// My top posts by number of stars let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")
Objective-C
// My top posts by number of stars FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"] child:[super getUid]] queryOrderedByChild:@"starCount"];
השאילתה הזו מאחזרת את הפוסטים של המשתמש מהנתיב במסד הנתונים על סמך מזהה המשתמש, ומסדרת אותם לפי מספר הכוכבים שכל פוסט קיבל. השיטה הזו, של שימוש במזהים כמפתחות אינדקס, נקראת "פיצול נתונים". תוכלו לקרוא עליה בהרחבה במאמר מבנה מסד הנתונים.
הקריאה ל-method 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.
Swift
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")
Objective-C
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];
במאמר איך מסודרים נתוני השאילתה מוסבר איך מסודרים סוגי נתונים אחרים.
סינון נתונים
כדי לסנן נתונים, אפשר לשלב כל אחת משיטות ההגבלה או הטווח עם שיטת הסידור כשיוצרים שאילתה.
| שיטה | שימוש |
|---|---|
queryLimitedToFirst |
מגדיר את המספר המקסימלי של פריטים שיוחזרו מתחילת רשימת התוצאות המסודרת. |
queryLimitedToLast |
מגדירה את המספר המקסימלי של פריטים שיוחזרו מסוף רשימת התוצאות המסודרת. |
queryStartingAtValue |
החזרת פריטים שגדולים מהמפתח או מהערך שצוין או שווים לו, בהתאם לשיטת הסידור שנבחרה. |
queryStartingAfterValue |
החזרת פריטים שגדולים מהמפתח או מהערך שצוינו, בהתאם לשיטת הסידור שנבחרה. |
queryEndingAtValue |
החזרת פריטים שקטנים מהמפתח או מהערך שצוינו או שווים להם, בהתאם לשיטת הסידור שנבחרה. |
queryEndingBeforeValue |
החזרת פריטים שהם קטנים מהמפתח או מהערך שצוינו, בהתאם לשיטת הסידור שנבחרה. |
queryEqualToValue |
הפונקציה מחזירה פריטים ששווים למפתח או לערך שצוינו, בהתאם לשיטת הסידור שנבחרה. |
בניגוד לשיטות הסידור, אפשר לשלב כמה פונקציות של הגבלה או טווח.
לדוגמה, אפשר לשלב את השיטות queryStartingAtValue ו-queryEndingAtValue כדי להגביל את התוצאות לטווח ערכים מסוים.
להגביל את מספר התוצאות
אפשר להשתמש בשיטות queryLimitedToFirst ו-queryLimitedToLast כדי להגדיר את המספר המקסימלי של צאצאים שיסונכרנו בקריאה חוזרת (callback) נתונה. לדוגמה, אם אתם משתמשים ב-queryLimitedToFirst כדי להגדיר מגבלה של 100, בהתחלה תקבלו עד 100 קריאות חוזרות (callbacks) של FIRDataEventTypeChildAdded. אם יש פחות מ-100 פריטים במסד הנתונים של Firebase, מופעלת קריאה חוזרת (callback) מסוג FIRDataEventTypeChildAdded לכל פריט.
כשהפריטים משתנים, אתם מקבלים קריאות חוזרות (callbacks) מסוג FIRDataEventTypeChildAdded לפריטים שנכנסים לשאילתה וקריאות חוזרות מסוג FIRDataEventTypeChildRemoved לפריטים שיוצאים ממנה, כך שהמספר הכולל נשאר 100.
בדוגמה הבאה אפשר לראות איך אפליקציית בלוגים לדוגמה יכולה לאחזר רשימה של 100 הפוסטים האחרונים של כל המשתמשים:
Swift
// 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
// 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 כדי למיין את הנתונים, הנתונים מוחזרים בסדר עולה לפי מפתח.
- הצאצאים עם מפתח שאפשר לנתח כמספר שלם של 32 ביט מופיעים קודם, בסדר עולה.
- אחריהם מופיעים צאצאים עם ערך מחרוזת כמפתח, ממוינים בסדר לקסיקוגרפי עולה.
queryOrderedByValue
כשמשתמשים ב-queryOrderedByValue, הצאצאים מסודרים לפי הערך שלהם. הקריטריונים לסידור זהים לאלה של queryOrderedByChild, אבל נעשה שימוש בערך של הצומת במקום בערך של מפתח צאצא שצוין.
queryOrderedByChild
כשמשתמשים ב-queryOrderedByChild, הנתונים שמכילים את מפתח הצאצא שצוין מסודרים באופן הבא:
- ילדים עם ערך
nilלמפתח הצאצא שצוין מופיעים ראשונים. - אחריהם מופיעים צאצאים עם הערך
falseבמפתח הצאצא שצוין. אם לכמה צאצאים יש ערך שלfalse, הם ממוינים לקסיקוגרפית לפי מפתח. - אחריהם מופיעים צאצאים עם הערך
trueבמפתח הצאצא שצוין. אם לכמה צאצאים יש ערך שלtrue, הם ממוינים לפי סדר לקסיקוגרפי לפי מפתח. - אחריהם מופיעים צאצאים עם ערך מספרי, בסדר עולה. אם לכמה צאצאים יש אותו ערך מספרי בצומת הצאצא שצוין, הם ממוינים לפי מפתח.
- מחרוזות מופיעות אחרי מספרים וממוינות בסדר לקסיקוגרפי עולה. אם לכמה צאצאים יש את אותו ערך בצומת הצאצא שצוין, הם מסודרים לפי סדר לקסיקוגרפי לפי מפתח.
- האובייקטים מופיעים בסוף וממוינים בסדר לקסיקוגרפי לפי מפתח בסדר עולה.
ניתוק מאזינים
המשקיפים לא מפסיקים לסנכרן נתונים באופן אוטומטי כשיוצאים מ-ViewController. אם לא מסירים את הצופה כמו שצריך, הוא ממשיך לסנכרן נתונים לזיכרון המקומי ושומר את כל האובייקטים שנתפסו בסגירה של הגורם המטפל באירועים, מה שעלול לגרום לדליפות זיכרון. כשכבר לא צריך את הצופה, מסירים אותו על ידי העברת ה-FIRDatabaseHandle המשויך ל-method removeObserverWithHandle.
כשמוסיפים בלוק קריאה חוזרת (callback) להפניה, מוחזר FIRDatabaseHandle.
אפשר להשתמש בכינויים האלה כדי להסיר את בלוק הקריאה החוזרת (callback).
אם נוספו כמה מאזינים להפניה למסד נתונים, כל מאזין נקרא כשמופעל אירוע. כדי להפסיק את סנכרון הנתונים במיקום הזה, צריך להסיר את כל הצופים במיקום באמצעות קריאה ל-method removeAllObservers.
הפעלת removeObserverWithHandle או removeAllObservers במאזין לא מסירה באופן אוטומטי מאזינים שרשומים בצומתי הצאצא שלו. צריך גם לעקוב אחרי ההפניות או נקודות האחיזה האלה כדי להסיר אותן.