0

As the title says I have a weird problem to retrieve simple data from Firebase, but I really can't figure out where I'd go wrong.

This is my schema:

enter image description here

And this the code:

import Firebase

let DB_BASE = Database.database().reference()

class FirebaseService {

    static let instance = FirebaseService()

    private var REF_BASE = DB_BASE
    private var REF_SERVICE_STATUS = DB_BASE.child("Service_Status")

    struct ServiceStatus {
        var downloadStatus: Bool
        var uploadStatus: Bool
    }

    func getServiceStatus() -> (ServiceStatus?) {
        var serviceStatus: ServiceStatus?

        REF_SERVICE_STATUS.observeSingleEvent(of: .value) { (requestSnapshot) in

            if let unwrapped = requestSnapshot.children.allObjects as? [DataSnapshot] {
                for status in unwrapped {
                    serviceStatus.downloadStatus = status.childSnapshot(forPath: "Download_Status").value as! Bool
                    serviceStatus.uploadStatus = status.childSnapshot(forPath: "Upload_Status").value as! Bool
                }
                // THANKS TO JAY FOR CORRECTION
                return sponsorStatus
            }
        }
    }
}

but at the end serviceStatus is nil. Any advice?

KENdi
  • 7,576
  • 2
  • 16
  • 31
user3582537
  • 414
  • 6
  • 20
  • The *return* is not used properly. In this case the return will execute way before the code in the Firebase function returns data from the server. Firebase is asyncronous and therefore you need to code as such. See [action after download](https://stackoverflow.com/questions/43027817/how-to-perform-an-action-only-after-data-are-downloaded-from-firebase/43029121#43029121) and [Firebase async task](https://stackoverflow.com/questions/38550634/swift-firebase-return-in-asynchron-task/38551937#38551937) – Jay Dec 19 '17 at 19:15
  • @Jay Thanks, I corrected that, but the problem is that serviveStatus is actually nil! Am I doing something wrong to retrieve data? – user3582537 Dec 19 '17 at 19:20

1 Answers1

0

I think you may be able to simplify your code a bit to make it more manageable. Try this

let ssRef = DB_BASE.child("Service_Status")
ssRef.observeSingleEvent(of: .value) { snapshot in
    let dict = snapshot.value as! [String: Any]
    let down = dict["Download_Status"] ?? false
    let up = dict["Upload_Status"] ?? false
}

the ?? will give the down and up vars a default value of false if the nodes are nil (i.e. don't exist)

Oh - and trying to return data from a Firebase asynchronous call (closure) isn't really going to work (as is).

Remember that normal functions propagate through code synchronously and then return a value to the calling function and that calling function then proceeds to the next line of code.

As soon as you call your Firebase function, your code is going to happily move on to the next line before Firebase has a chance to get the data from the server and populate the return var. In other words - don't do it.

There are always alternatives so check this link out

Run code only after asynchronous function finishes executing

Jay
  • 34,438
  • 18
  • 52
  • 81