0

This is my data structure. enter image description here

This is how I load club data and its address.

func loadClubs() {

        ref = Database.database().reference()
        ref.child("club").observe(DataEventType.childAdded, with: { (clubSnapshot) in
            if let clubDict = clubSnapshot.value as? [String : AnyObject] {
                let name = clubDict["name"] as! String
                let explanation = clubDict["explanation"] as! String
                let courtNum = clubDict["courtNum"] as! Int
                let membershipFee = clubDict["membershipFee"] as! Int
                let visitorFee = clubDict["visitorFee"] as! Int
                let hasCarParking = clubDict["hasCarParking"] as! Bool
                let club2 = Club2(name: name, explanation: explanation, courtNum: courtNum, membershipFee: membershipFee, visitorFee: visitorFee, hasCarParking: hasCarParking)
                self.club2Array.append(club2) // Add to clubArray
                print(self.club2Array)
                self.tableView.reloadData()
            }
            let addressRef = Database.database().reference()
            addressRef.child("address").child(clubSnapshot.key).observe(DataEventType.childAdded, with: { (addressSnapshot) in
                if let addressDict = addressSnapshot.value as? [String: AnyObject] {

                    let clubAddress = ClubAddress(postCode: addressDict["postcode"] as! String, cityName: addressDict["city"] as! String, ward: addressDict["ward"] as! String, address1: addressDict["address1"] as! String, address2: addressDict["address2"] as! String)

                    self.addressArray.append(clubAddress)
                    print(self.addressArray)
                }
            })
        })
    }

basically, after retrieving each snapshot of club, I get club's key (-KsJB9TkoGNIkiZFGg7), then use that key to retrieve address. However, print(self.addressArray) doesn't not print anything. I add a debug breakpoint at if let addressDict = addressSnapshot.value as? [String: AnyObject] { , it does not stop the debug process. Why is it not calling? What do I miss here?

John
  • 3,888
  • 11
  • 46
  • 84

1 Answers1

3

Ah! Your code is very close.

Keep in mind that .childAdded iterates over all of the child nodes and loads each one.

In your case, you don't want to iterate over all of the address nodes, you just want one, and don't want to leave an observer.

To do that, we load the specific node child data of the address node, by observeSingleEvent(of: .value. Here's a snippet of the important part.

let addressRef = Database.database().reference()
addressRef.child("address").child(clubSnapshot.key)
          .observeSingleEvent(of: .value, with: { (addressSnapshot) in
    let dict = addressSnapshot.value as! [String: Any]
    let address = dict["address1"] as! String
    print(address)
Jay
  • 34,438
  • 18
  • 52
  • 81
  • Thanks. But your post does not answer my question. print(self.addressArray) doesn't not print anything. I add a debug breakpoint at if let addressDict = addressSnapshot.value as? [String: AnyObject] { , it does not stop the debug process. – John Aug 29 '17 at 00:39
  • It does answer the question! The let statement fails because you cannot use a .childAdded observer here. It needs to be .value so you load the child nodes and not *iterate* over the child nodes - because there are not any other child nodes. – Jay Aug 29 '17 at 00:42
  • I just figure out it is because I got [MyBadminton.Club2, MyBadminton.Club2] --> then self.tableview.reload() is called while there is only one item in [MyBadminton.ClubAddress]. I put self.tableview.reload() to address closure and I got it works!. Anyway, thanks for your help. – John Aug 29 '17 at 00:55
  • That's not going to be a good solution. The tableview is being reloaded over and over which won't be a good experience for the user. If there's 500 items that's 500 reloads. On top of that, if it's reloading after each address lookup, that's thousands. And that also adds thousands of observers to the address node. – Jay Aug 29 '17 at 01:36
  • I used your code too. But the problem of the question is due to where I put self.tableview.reload() – John Aug 29 '17 at 07:27
  • @John Great question. There's a number of different solutions but one of the coolest is to leverage the fact that .value events fire *after* .childAdded events. To do that add a observeSingleEvent(.value) to the addressRef node and in it's closure add a tableView.reloadData. For more details see [this question](https://stackoverflow.com/questions/37103192/swift-firebase-sort-posts-in-tableview-by-date/37126528#37126528) and [another question](https://stackoverflow.com/questions/41082347/swift-firebase-loading-records-with-long-delay/41108155#41108155). That should get you a good solution. – Jay Aug 29 '17 at 12:19