How to Write to a Variable from Within The Firebase Getdocument Function (Swift)

How do I save data from cloud firestore to a variable in swift?

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

How do I get a document from Firebase that is ordered by a variable (DocumentName is not known)

Here is a real-world example of how you can retrieve a value from your Firestore database. In this case I've customized a query to your needs using the code provided in the Firestore documentation on this page, under "Add Data".

Please try the following:

  func getSingleproperty() {
var desiredProperty: String!
let docRef = db.collection("UnKnownErrorMessages").document("Error1234")

docRef.getDocument { (document, error) in
if let document = document, document.exists {
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
print("Document data: \(dataDescription)")

if let allPropertiesInDocument = document.data() {

let nameOfPropertyIwantToRetrieve = "errorMessage"

if let selectedProperty = allPropertiesInDocument[nameOfPropertyIwantToRetrieve] {
desiredProperty = selectedProperty as? String
}
}
print("Value of desiredProperty is \(desiredProperty)")

} else {
print("Document does not exist")
}
}
}

Assign value of a Firestore document to a variable

The Firebase call is an asynchronous function. It takes extra time to execute because it's talking to a server (as you've noted) - as a result, the completion block (the block that defines document and err in your example) happens at a different time, outside of the rest of the body of the function. This means you can't return a value from inside it, but you can pass another closure through to it, to execute later. This is called a completion block.

func readAvailableLists(forUser user: String, completion: @escaping ([String]?, Error?) -> Void) -> [String] {
let db = Firestore.firestore()
db.collection("userslist").document(user).getDocument { (document, err) in
if let document = document, document.exists {
// We got a document from Firebase. It'd be better to
// handle the initialization gracefully and report an Error
// instead of force unwrapping with !
let strings = (UserInformationDocument(dictionary: document.data()!)?.lists!)!
completion(strings, nil)
} else if let error = error {
// Firebase error ie no internet
completion(nil, error)
}
else {
// No error but no document found either
completion(nil, nil)
}
}
}

You could then call this function elsewhere in your code as so:

readAvailableLists(forUser: "MyUser", completion: { strings, error in
if let strings = strings {
// do stuff with your strings
}
else if let error = error {
// you got an error
}
})

How to set variables from a Firebase snapshot (swift)

Try using:-

FIRDatabase.database().reference().child("users/userID/ls").observeSingleEvent(of : .value, with : {(Snap) in 

if let snapDict = Snap.value as? [String:AnyObject]{

for each in snapDict{

print("\(each.value["fromId"] as! String)")

}
}
})

SwiftUI - Get field value from a Firebase document

The reason why the value is never found is because the network request you are making takes time to retrieve that data. By the time it reaches the return statement the data from firebase has not been been retrieved yet so it will just return the value it was initially set to which was an empty string. What you should do is add a completion handler to the function so that once the data is finally retrieved you can then return it.

struct ContentView: View {
@State private var text: String = ""

var body: some View {
Text(text)
.onAppear {
readUserInfo("sydQu5cpteuhPEgmHepn") { text in
self.text = text
}
}
}

func readUserInfo(_ uid: String, _ completion: @escaping (String) -> Void) {
let db = Firestore.firestore()
let docRef = db.collection("users").document(uid)
docRef.getDocument { document, error in
if let document = document, document.exists {
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
print("Document data: \(dataDescription)")
completion(dataDescription)
} else {
completion("Document does not exist")
}
}
}
}


Related Topics



Leave a reply



Submit