Arnav Kartikeya
Arnav Kartikeya

Reputation: 19

Code not executing after .observe firebase method swift4

I have a structure in which users are registering for events, and the registered events are stored as the following:

enter image description here

I am trying to access the registeredEvents and display the children on a table view. So far, I have done this:

 override func viewDidLoad() {
    super.viewDidLoad()
    let id = Auth.auth().currentUser?.uid
    let ref = Database.database().reference()
    ref.child("users").child(id!).child("registeredEvents").observeSingleEvent(of: .value, with: { snapshot in
           print(snapshot.childrenCount)
        for rest in snapshot.children.allObjects as! [DataSnapshot] {
               print(rest.value!)
               self.eventsArray.append(rest.value!)
            }
    })

    print(eventsArray)
    self.tblEvents.dataSource = self
    self.tblEvents.delegate = self
}

It prints all the children's values like it is supposed to, but it wont do anything after that observe closure. It will not print eventsArray, or anything that I put in a print statement. Also, eventsArray only contains things it had before the closure. Could you please let me know why this is happening, and what needs to be done to fix it, specifically in the form of code?

Upvotes: 0

Views: 51

Answers (1)

Jay
Jay

Reputation: 35648

Firebase is asynchronous - code runs much faster than the internet so the code following the closure

print(eventsArray)

will actually run before the code in the closure. Also, Firebase data is only valid inside that closure so ensure you're working with data in the closure first. In this case to correct it try this

 override func viewDidLoad() {
    super.viewDidLoad()

    self.tblEvents.dataSource = self
    self.tblEvents.delegate = self

    let id = Auth.auth().currentUser?.uid
    let ref = Database.database().reference()
    ref.child("users").child(id!).child("registeredEvents").observeSingleEvent(of: .value, with: { snapshot in
        print(snapshot.childrenCount)
        for rest in snapshot.children.allObjects as! [DataSnapshot] {
            print(rest.value!)
            self.eventsArray.append(rest.value!)
        }
        print(self.eventsArray) //or refresh your tableView here
    })
}

The code is passing a bunch of .value objects, which are dictionaries, to your eventsArray. You may want to consider crafting objects to hold that dictionary data and adding those objects to the array instead.

    for restSnap in snapshot.children.allObjects as! [DataSnapshot] {
       let event = EventClass(withSnap: restSnap)
       self.eventsArray.append(event)
    }

the dataSource array would look like this

var eventsArray = [EventClass]()

and the EventClass would be

class EventClass {
    var first_name = ""
    var event_key = ""

    init(withSnap: DataSnapshot) {
        self.event_key = withSnap.key
        self.first_name = withSnap.childSnapshot(forPath: "First name").value ?? "No first name"
        let registeredEventsSnap = withSnap.childSnapshot(forPath: "registeredEvents")
        //iterate over the registeredEventsSnap to get all the events
    }
}

Upvotes: 1

Related Questions