如何更深入地阅读Firebase Swift 3的快照?

在当前的实现中,我可以通过创buildFireBaseData实例来读取属于var uid的预订,该实例使用Firebase数据库中指定的值进行初始化。

我需要为/Users节点下的所有用户预订所有预订,然后将它们分配给一个数组,以便我可以在UITableVIew中显示值。 我不知道如何更深入地阅读快照。

Firebase数据库结构:

Firebase树

 // create a reference to Firebase var dbRef:FIRDatabaseReference! var uid = "lwrUjaDCcoOcx4K2gioO76JWp2i2" // this array will hold all bookings for the logged in user var bookingInfo = [FireBaseData]() override func viewDidLoad() { super.viewDidLoad() dbRef = FIRDatabase.database().reference().child("Users") startObservingDB() // observe the database for value changes } func startObservingDB() { dbRef.child("lwrUjaDCcoOcx4K2gioO76JWp2i2"). observe(.value, with: { (snapshot: FIRDataSnapshot) in // an instance of FireBaseData holding all bookings belonging to currentUid var newBookingInfo = [FireBaseData]() for booking in snapshot.children { // after each iteration create an instance of FireBaseData with // 'booking' for the current iteration & assign it to bookingItem let bookingItem = FireBaseData(snapshot: booking as! FIRDataSnapshot) // append the bookingItem after each iteration to newBookingInfo array newBookingInfo.append(bookingItem) } //assign newBookingInfo to global variable bookingInfo so it can be used globally within the class self.bookingInfo = newBookingInfo }, withCancel: { (Error:Any) in }) } // use this struct to retrieve data from the snapshot received struct FireBaseData { var BookingAmount:String! var BookingNumber:String! . . ... and so on } init(snapshot:FIRDataSnapshot){ if let BookingAmountContent = (snapshot.value! as? NSDictionary)?["BookingAmount"] as? String { BookingAmount = BookingAmountContent } if let BookingNumberContent = (snapshot.value! as? NSDictionary)?["BookingNumber"] as? String { BookingNumber = BookingNumberContent . . .... and so on } snapshot.children_IS <FTransformedEnumerator: 0x60800023a380> snapshot.value_IS({ lwrUjaDCcoOcx4K2gioO76JWp2i2 = { 718565122 = { BookingAmount = 12; BookingNumber = 718565122; DateAndTime = "Mon, 26 Sep 2016 18:30"; EmailAddress = "1@gmail.com"; FlatNumber = 10; FrequecyAmount = 48; FrequencyName = Once; FullName = "Michael "; PhoneNumber = 25558882522; PostCode = SE13TYY; SelectedBathRow = 4; SelectedBedRow = 3; StreetAddress = "High Street"; SuppliesAmount = 5; SuppliesName = "Bring cleaning supplies"; insideCabinets = 0; insideFridge = 1; insideOven = 0; interiorWindows = 1; laundryWash = 1; }; 890149009 = { BookingAmount = 73; BookingNumber = 890149009; DateAndTime = "Sat, 01 Oct 2016 13:30"; EmailAddress = "1@gmail.com"; FlatNumber = 10; FrequecyAmount = 48; FrequencyName = Once; FullName = "Michael "; PhoneNumber = 25558882522; PostCode = SE13TYY; SelectedBathRow = 4; SelectedBedRow = 3; StreetAddress = "High Street"; SuppliesAmount = 5; SuppliesName = "Bring cleaning supplies"; insideCabinets = 0; insideFridge = 1; insideOven = 0; interiorWindows = 1; laundryWash = 1; }; }; xd5rwZzUqoRbfMp2rq5pTxuRB3s1 = { 116928124 = { BookingAmount = 22; BookingNumber = 116928124; DateAndTime = "Fri, 16 Dec 2016 16:30"; EmailAddress = "bibscy@gmail.com"; FlatNumber = 10; FrequecyAmount = 22; FrequencyName = "Every week"; FullName = Mi; PhoneNumber = 28488824; PostCode = RTRFHGT; SelectedBathRow = 3; SelectedBedRow = 1; StreetAddress = "12 High St"; SuppliesAmount = 0; SuppliesName = "I have cleaning supplies"; TimeStampBookingSavedInDB = 1481886718; TimeStampDateAndTime = 1481905800; insideCabinets = 0; insideFridge = 0; insideOven = 0; interiorWindows = 0; laundryWash = 0; }; 328241274 = { BookingAmount = 22; BookingNumber = 328241274; DateAndTime = "Sun, 18 Dec 2016 16:30"; EmailAddress = "bibscy@gmail.com"; FlatNumber = 10; FrequecyAmount = 22; FrequencyName = "Every week"; FullName = Mi; PhoneNumber = 28488824; PostCode = RTRFHGT; SelectedBathRow = 3; SelectedBedRow = 1; StreetAddress = "12 High St"; SuppliesAmount = 0; SuppliesName = "I have cleaning supplies"; TimeStampBookingSavedInDB = 1481888650; TimeStampDateAndTime = 1482078600; insideCabinets = 0; insideFridge = 0; insideOven = 0; interiorWindows = 0; laundryWash = 0; }; }; }) 

根据@Jaybuild议更新答案

 *Problem : with this implementation `queryOrdered(byChild:)` has no effect.* func startObservingDB() { dbRef.queryOrdered(byChild: "TimeStampDateAndTime").observe(.value, with: { (snapshot: FIRDataSnapshot) in // an instance of FireBaseData holding all bookings under currentUid var newBookingInfo = [FireBaseData]() //iterate over each user node child for user_child in snapshot.children { //user_snap is each user let user_snap = user_child as! FIRDataSnapshot //now iterate over each booking for booking in user_snap.children { // after each iteration through snapshot.children, create an instance of FireBaseData with 'booking' for the current iteration & assign it to bookingItem let bookingItem = FireBaseData(snapshot: booking as! FIRDataSnapshot) // append the bookingItem after each iteration to newBookingInfo array newBookingInfo.append(bookingItem) } } //assign newBookingInfo to global variable bookingInfo so it can be used globally within the class self.bookingInfo = newBookingInfo // reload the data every time FIRDataEventType is triggered by value changes in Database self.tableView.reloadData() }, withCancel: { (Error:Any) in print("Huge \(Error)") }) //Set the estimatedRowHeight of your table view tableView.estimatedRowHeight = 44.0 // Set the rowHeight of your table view to UITableViewAutomaticDimension tableView.rowHeight = UITableViewAutomaticDimension } // end of startObservingDB() 

预订不按升序排列

@Jay还build议在代码中对从Firebase DB检索到的对象数组进行sorting,而不是使用Firebase提供的queryOrdered(by:_)方法。 这是我如何sorting和过滤数组。

  // sort the array in place so that the most recent date will appear first self.bookingInfo.sort(by: {(DateAndTimeObject_1,DateAndTimeObject2) -> Bool in DateAndTimeObject_1.TimeStampDateAndTime < DateAndTimeObject2.TimeStampDateAndTime }) // filter each element in the array against the condition specified in the body of the closure self.bookingInfo = self.bookingInfo.filter({(firstElementInArray) -> Bool in firstElementInArray.TimeStampDateAndTime == 1483201800 }) 

那么您在这里后面是每个用户节点内的每个预订节点

模板看起来像:

 users uid_0 booking_0 booking_amount: "12" booking_1 booking_amount: "14" 

读取.value读入用户节点中的所有内容。

每个用户节点有多个预订子节点,因此我们需要遍历这些子节点以获取其子值。

在每个孩子的内部是我们想要得到的关键:值对,在这个例子中是booking_amount和值。

 let usersRef = myRootRef.child(byAppendingPath: "users") usersRef?.observe(.value, with: { snapshot in if ( snapshot!.value is NSNull ) { print("not found") } else { for user_child in (snapshot?.children)! { //iterate over each user node child //assign the user_child enumerator to a snapshot let user_snap = user_child as! FDataSnapshot for booking in user_snap.children { //now iterate over each booking //booking is a enumerator so make it a snapshot let bookingSnap = booking as! FDataSnapshot let dict = bookingSnap.value as! [String: String] let amount = dict["booking_amount"] print(amount!) } } } })