Search code examples
swiftxcodefirebase-realtime-databaseboolean-logicboolean-expression

Boolean function returns default value until real value checked in Firebase DB XCode Swift


I've the following boolean function:

func checkIfLocateAcessGiven(uid: String) -> Bool {
    
    print("checkIfLocateAcessGiven")
    
    var currentUserID = UserDefaults.standard.string(forKey: "currentUserID")
    
    var statusStr = false
    
    print("checkIfLocateAcessGiven statusStr 1: \(statusStr)")
    
    Database.database().reference().child("Locate").child(currentUserID!)
        .observeSingleEvent(of: .value, with: { (dataSnapshot) in
        
            if(dataSnapshot.exists()){
                
                if(dataSnapshot.hasChild("RequestedTo")){
                    
                    if(dataSnapshot.childSnapshot(forPath: "RequestedTo").hasChild(uid)){
                        
                        var status = dataSnapshot.childSnapshot(forPath: "RequestedTo").childSnapshot(forPath: uid).value as! String ?? ""
                        
                        if(status == "true"){
                            
                            statusStr = true
                            
                            print("checkIfLocateAcessGiven statusStr 2: \(statusStr)")
                            
                        }else {
                            
                            statusStr = false
                            
                            print("checkIfLocateAcessGiven statusStr 3: \(statusStr)")
                        }
                        
                    }else {
                        
                        statusStr = false
                        
                        print("checkIfLocateAcessGiven statusStr 4: \(statusStr)")
                    }
                    
                }else {
                    
                    statusStr = false
                    
                    print("checkIfLocateAcessGiven statusStr 5: \(statusStr)")
                }
                
            }else {
                
                statusStr = false
                
                print("checkIfLocateAcessGiven statusStr 6: \(statusStr)")
            }
            
    })
    
    print("checkIfLocateAcessGiven statusStr 7: \(statusStr)")
    
    return statusStr
    
}

When I call this function I get the following results:

checkIfLocateAcessGiven
checkIfLocateAcessGiven statusStr 1: false
checkIfLocateAcessGiven statusStr 7: false
checkIfLocateAcessGiven statusStr 2: true

Since false is returned at first, my code takes a different flow, and later true is returned, how can I wait in the boolean function until the real value is checked. There's delay of approx. 1 second between

checkIfLocateAcessGiven statusStr 7: false

and

checkIfLocateAcessGiven statusStr 2: true

I want the boolean to wait and check the real value and then return the value, in this case true but it's currently returning false

Could someone please help me with this?


Solution

  • This is an asynchronous function, meaning that it cannot return synchronously a result which it needs to obtain asynchronously, for example from a web service, like Firebase.

    You can't (or rather shouldn't) wait for it, and instead use a callback to notify when the value has been obtained.

    If you don't know about async programming, there are a lot of material online and you should definitely read more about it, because this answer won't be comprehensive.

    The basic idea is that your async function takes in a closure that would be invoked on completion:

    func checkIfLocateAcessGiven(uid: String, completion: (Bool) -> Void) {
       // your setup code
    
       Database.database().reference().child("Locate").child(currentUserID!)
            .observeSingleEvent(of: .value, with: { (dataSnapshot) in
             // checks, ifs, etc..
    
                 // whenever you have the result
                 completion(true) // or completion(false)
    
       }
    }
    

    The caller would specify the completion callback, which would be invoked asynchronously:

    print("before")
    checkIfLocateAcessGiven(uid: "1234") { result in
       print("async call result: ", result) 
       // do whatever you need to do with the result
    }
    print("after")
    

    The output of the above would be something like this:

    before
    after
    async call result: true
    

    The first two lines would print immediately one after another, and the third line would take a while, however long the Firebase call takes.