Search code examples
iosswiftfirebasefirebase-realtime-databasefirebase-queue

What could cause a Swift/Firebase app to act up the first time it is installed and never again?


What doesn't work the first time?:

The order in which database entries that I fetch displays

I am running this

1st part In ViewDiDLoad

let thisUserRef = Database.database().reference().child("users").child(uid)
let myPeopleRef = thisUserRef.child("likers")
myPeopleRef.queryLimited(toLast: 30).observeSingleEvent(of: .value, with: { snapshot in
    let userArray = snapshot.children.allObjects as! [DataSnapshot]
    for person in userArray.reversed() where uid == Auth.auth().currentUser?.uid  {
        let personUid = person.value as! String
        self.printPersonInfo(uid: personUid) //// this calls a DispatchQueue.main.async that appends the data in the array and reloads
    }
})

  func printPersonInfo(uid: String) {
        print(uid)
        let usersRef = Database.database().reference().child("users")
        let thisUser = usersRef.child(uid)
        thisUser.observeSingleEvent(of: .value, with: { snapshot in
            let xx = snapshot.childSnapshot(forPath: "xx").value as? String ?? "No Entry"
            let yy = snapshot.childSnapshot(forPath: "yy").value as? String ?? "No Entry"
            let rr = snapshot.childSnapshot(forPath: "rr").value as? String ?? "No Entry"
            let zz = snapshot.childSnapshot(forPath: "zz").value as? String ?? "No Entry"
            let ll = snapshot.childSnapshot(forPath: "ll").value as? String ?? "No Entry"
            let p = Usery(xx: xx, yy: yy, rr: rr, zz: zz, ll: ll)
            self.person.append(p)
            print(self.person, "person")
            self.table.reloadData()
        })
}
//////this gets the various data elements of the users that get displayed. 
///////So to summarize, the query determines which users get displayed. This func determined which data of those users gets displayed.

Example of database entires of last 30

user K
user B
user F
user G
user K
user B
user K
.....

The only time this doesn't work is if you install the app clean for the first time. Then the order in which it displays is

user K
user K
user B
user B
user F
user G

JSON

users 
  uid 
   likers
      chailbyAutoID: uid1
      chailbyAutoID: uid2
  

Solution

  • One possible solution is to use DispatchGroups to control the loading of the data, which therefore would control the sequence in which a class var array is populated.

    In this example, we'll read all of the users uids from a users node and populate an array. It would look like this

    users
       uid_0
          name: "Wilbur"
       uid_1:
          name: "Orville"
    

    We'll then go back and re-read additional user data from that node, using array.reversed() so they populate a result array in reversed order. We'll need a class to store each user data and then a class array to store all of the users are they are read in. Here's the class vars

    struct PersonClass {
       var uid = ""
       var name = ""
    }
    
    var personArray = [PersonClass]()
    

    and the code to populate them in reverse order

    func readUserDataUsingDispatch() {
        let ref = self.ref.child("users") //self.ref points to my firebase
        ref.observeSingleEvent(of: .value, with: { snapshot in
    
            //this just builds and array of user id's - we'll iterate through them to read the rest of the data
            let idArray = snapshot.children.allObjects as! [DataSnapshot]
            var allKeys = [String]()
            for userSnap in idArray {
                allKeys.append( userSnap.key ) //[uid_0, uid_1] etc
            }
    
            let group = DispatchGroup()
    
            for uid in allKeys.reversed() {
                group.enter()
                let thisUser = ref.child(uid)
    
                thisUser.observeSingleEvent(of: .value, with: { userSnapshot in
                    let name = userSnapshot.childSnapshot(forPath: "name").value as! String
                    let person = PersonClass(uid: uid, name: name)
                    self.personArray.append(person)
                    print("added uid")
                    group.leave()
                })
            }
    
            group.notify(queue: .main) {
                print("done")
            }
        })
    }
    

    when you run the code this is the output, indicating the data is loaded

    added uid
    added uid
    done
    

    and then when printing the class var personArray it's the users in reverse order.

    uid_1 Orville
    uid_0 Wilbur