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
Assigning values from Firestore to variables in swift
Here is a very simplified version of what you are trying to do. Once you have your data in hand, you can unwrap them individually, like in the example below, or map them to custom Swift objects. But it appears that your question is only about getting data from Firestore.
featuredAttractionsQuery.addSnapshotListener { (snapshot, error) in
guard let snapshot = snapshot else { // unable to get snapshot
if let error = error {
print(error)
}
return // terminate query
}
guard !snapshot.isEmpty else { // snapshot is empty
print("snapshot is empty")
return // terminate query
}
for doc in snapshot.documents { // iterate through documents
guard let caption = doc.get("caption") as? String,
let imagePath = doc.get("imagePath") as? String else {
continue // if we can't get these two values,
// move to next iteration and continue loop
// calling return here would exit the function
}
// do something with this document's data
// most likely you'll parse it into a native object
// and add it to an array
}
// the loop is complete, reload the table view or collection view
}
There is a lot more that goes into this, such as using dispatch queues to parse your data in the background and dispatch groups to handle image downloads which return asynchronously. But this is the basic starting point that virtually all parsing is founded on.
Can't pass variable value from firebase firestore to another class SWIFT
you need to use completion handler because its async function
func getPrice(completion:@escaping (Prices?,Error?)-> Void) {
PricingRef = Firestore.firestore().collection("ProductXYZ")
PricingRef.getDocuments { (snapshot, error) in
if let err = error {
debugPrint("Error fetching data \(err)")
completion(nil,err)
}
else {
guard let snap = snapshot else { return }
for document in snap.documents {
let data = document.data()
let std = data["standard"] as! String
self.price.standardPrice = Int(std)!
print(self.price.standardPrice!) // This print the intended result
completion(self.price.standardPrice,nil)
}
}
}
}
How to use
Functions().getPrice { (price, error) in
if let err = error {
// do something if you get error
} else if let getPrice = price {
// use price
self.price = getPriice
}
Cloud Firestore & Swift - Retrieve Document & assign fields to variables for processing
I would recommend this way:
let docRef = db.collection("ask").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)")
let data = document.data()
let q1 = data!["q1"]! as? Bool ?? true
if q1 == false {
//false code
} else {
//true code
}
} else {
print("Document does not exist")
}
}
How to properly set State with Firestore getDocuments
The only thing that's wrong is your expectations about how getDocuments
works.
getDocuments
is asynchronous, and the callback (completion) you pass to it is executed after it returns. Print something in the callback and it'll be more clear what's actually going on.
Given that, checkDoc
cannot possibly return the correct value synchronously unless you do something to make it block (which you should not do). You will need to handle all query results asynchronously.
Related Topics
How to Display Data from Firebase Faster
How to Perform an Action Only After Data Are Downloaded from Firebase
How to Make the Scroll of a Tableview Inside Scrollview Behave Naturally
Lesser Than or Greater Than in Swift Switch Statement
How to Init a Uibutton Subclass
Multiple Type Constraints in Swift
@Noescape Attribute in Swift 1.2
How to Create Custom Notifications in Swift 3
How to Create Swift Class for Category
How to Use Alamofire with Custom Headers
How to Create a Fixed-Size Array of Objects
How to Make Class Methods/Properties in Swift
Add Subtitle Under the Title in Navigation Bar Controller in Xcode
What Are the Differences Between Throws and Rethrows in Swift