简体   繁体   中英

How to read deeper into a snapshot Firebase Swift 3?

With the current implementation I can read the bookings belonging to var uid by creating an instance of a structure FireBaseData which is initialized with the values specified in the Firebase Database.

I need to get all bookings for all users under /Users node and then assign them to an array so that I can display the values in a UITableVIew. I don't know how to read deeper into the snapshot.

Firebase Database Structure:

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 = "b@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 = "bi@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;
    };
    };
 })

Updated Answer according to @Jay suggestion

*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 also suggested that to sort the array of objects retrieved from Firebase DB in code rather than using queryOrdered(by:_) method provided by Firebase. Here is how I am sorting and filtering the array.

     // 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
   })
    

So what you after here is each booking node within each users node

A template would look like:

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

Read by .value which reads in everything in the users node.

Each user node has multiple booking children so we will then need to iterate over those to get their child values.

Inside each child is the key: value pairs we want to get, in this example, booking_amount and the value.

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!)
        }      
      }
    }
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM