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

109 Views Asked by At

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
  
1

There are 1 best solutions below

1
On BEST ANSWER

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