0

I want to save a particular field from a document into a variable. My code so far:

func getDocument(path: String, field: String? = "nil") -> some Any{
    var returnVar : Any = "DEFAULT VAL"
    var db: Firestore!
    db = Firestore.firestore()
    
    let docRef = db.document(path)
    docRef.getDocument { (document, error) in
        if let document = document, document.exists {
            if(field != "nil"){
                let property =  document.get("phrase") ?? "nil"
                returnVar = property
                return;
            }
            else{
                let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
                returnVar = dataDescription
                return;
            }
        } else {
            print("Document does not exist")
            returnVar = -1
            return;
        }
    }
    print("Returned val: " + (returnVar as! String))
    return returnVar;
}

It seems however that my getDocument method returns before ever reading the data from firebase(coming from pure OOP land, I have no clue how this even happens) From debugging, it seems execution simply skips over the entire docRef.getDocument code and jumps to the return statement. It is only after the function returns does the code in the docRef.getDocument block get executed(what? how does code in a function that has already returned continue to execute?).

How can I store a particular field in a variable and return it?

Dennis Kozevnikoff
  • 2,078
  • 3
  • 19
  • 29

1 Answers1

6

That's because Firestore function getDocument is an asynchronous function and it returns immediately and after that it continues to execute the code inside it. If you want to return a particular value from here, you need to use completion Handler. Your function may look like this.

func getDocument(path: String, field: String? = "nil", completion:@escaping(Any)->()) {
var returnVar : Any = "DEFAULT VAL"
var db: Firestore!
db = Firestore.firestore()

let docRef = db.document(path)
docRef.getDocument { (document, error) in
    if let document = document, document.exists {
        if(field != "nil"){
            let property =  document.get("phrase") ?? "nil"
            returnVar = property
            completion(returnVar)
        }
        else{
            let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
            returnVar = dataDescription
            completion(returnVar)
        }
    } else {
        print("Document does not exist")
        returnVar = -1
        completion(returnVar)
      }
    }
  }

Then call the function in viewDidLoad or in any other function like this.

getDocument(path: path, field: field){(value) in
    print(value)
}

You can checkout more about Completion Handlers here

Fahad Ali
  • 205
  • 1
  • 9