Hi this function is producing an unexpected result for me. I'm new to programming so I appreciate any help understanding this.
The first print statement prints second to the last print statement. I think its because maybe the call to Firebase is still waiting for results even though the function completed the operation? How can I make it so that the function doesn't return an empty array?
func readFromDatabase() -> [[String]] {
let db = Firestore.firestore()
db.collection("Letters").getDocuments { (snapshot, error) in
if error != nil {
print(error?.localizedDescription ?? "error")
} else {
for document in (snapshot?.documents)! {
// let fetchedData = document.data() //gets all data from all documenters unorganized
let firstLetter = document.get("1") as! String
let secondLetter = document.get("2") as! String
let thirdLetter = document.get("3") as! String
let fourthLetter = document.get("4") as! String
let fifthLetter = document.get("5") as! String
let sixthLetter = document.get("6") as! String
let seventhLetter = document.get("7") as! String
let eighthLetter = document.get("8") as! String
let organizedData = [firstLetter, secondLetter, thirdLetter, fourthLetter, fifthLetter, sixthLetter, seventhLetter, eighthLetter]
self.databaseData = organizedData
self.make2darray.append(self.databaseData) //makes 2darray
} //closing fetch
} //closing else statement
print("printing", self.make2darray) // works ok
} //closing snapshot
print("printing outside snapshot", self.make2darray) //returns empty array
return self.make2darray //returns empty array
} //closing function
UPDATE: I've made the following changes to the code after reading and trying a few things. This should work as far as I understood what I read but I'm still getting an empty array.
func readFromDatabase(completion: @escaping ([[String]]) -> Void) {
let db = Firestore.firestore()
let dispatchGroup = DispatchGroup()
db.collection("Letters").getDocuments { (snapshot, error) in
if error != nil {
print(error?.localizedDescription ?? "error")
} else {
dispatchGroup.enter()
for document in (snapshot?.documents)! {
// let fetchedData = document.data() //gets all data from all documenters unorganized
let firstLetter = document.get("1") as! String
let secondLetter = document.get("2") as! String
let thirdLetter = document.get("3") as! String
let fourthLetter = document.get("4") as! String
let fifthLetter = document.get("5") as! String
let sixthLetter = document.get("6") as! String
let seventhLetter = document.get("7") as! String
let eighthLetter = document.get("8") as! String
let organizedData = [firstLetter, secondLetter, thirdLetter, fourthLetter, fifthLetter, sixthLetter, seventhLetter, eighthLetter]
self.databaseData = organizedData
self.make2darray.append(self.databaseData) //makes 2darray
} //closing fetch
dispatchGroup.leave()
} //closing else statement
//print("printing", self.make2darray) // works ok
dispatchGroup.notify(queue: .main){
completion(self.make2darray)
}
} //closing snapshot
} //closing function
you may be calling the print statement too early, try calling it after the function has run
override func viewdidload() {
super.viewDidLoad()
readFromDatabase()
print (make2darray)
}
Okay to anyone looking for an answer to this in the future. Here is how I was able to resolve the issue. I had to create an observer with a notification key.
The notification key was created as a variable right under the class declaration like this: let notificationKey = "#####"
. The hash would be a unique key like your website name or something.
In the viewDidLoad, I called createObserver() and called readFromDatabase() right after.
What is happening is that while the readFromDatabase() function is getting the data, the observer is waiting to hear a signal from the Notification Center. When the work is complete the Notification Center triggers the key we created that tells the observer the process is complete. That means now that "make2darray" has the complete data records pulled from the database and is ready for use. We must also remove the observer right after to not cause any issues later.
This code is crude I'm sure, but it works. I'm a new programmer, so use whatever way gets the same results for you. Good luck to you.
func createObserver(){
//listening to hear if the database call is complete
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.readFromDatabase), name: NSNotification.Name(rawValue: notificationKey), object: nil)
}
@objc func readFromDatabase() {
let db = Firestore.firestore()
db.collection("Letters").getDocuments { (snapshot, error) in
if error != nil {
print(error?.localizedDescription ?? "error")
} else {
for document in (snapshot?.documents)! {
// let fetchedData = document.data() //gets all data from all documenters unorganized
let firstLetter = document.get("1") as! String
let secondLetter = document.get("2") as! String
let thirdLetter = document.get("3") as! String
let fourthLetter = document.get("4") as! String
let fifthLetter = document.get("5") as! String
let sixthLetter = document.get("6") as! String
let seventhLetter = document.get("7") as! String
let eighthLetter = document.get("8") as! String
let organizedData = [firstLetter, secondLetter, thirdLetter, fourthLetter, fifthLetter, sixthLetter, seventhLetter, eighthLetter]
self.databaseData = organizedData
self.make2darray.append(self.databaseData) //makes 2darray
} //closing fetch
} //closing else statment
//Notifies the observer that the process is complete
NotificationCenter.default.post(name: NSNotification.Name(rawValue: self.notificationKey), object: nil)
//Removing the observer
NotificationCenter.default.removeObserver(self)
} //closing database call
//verifying all entries are present
//print("printing outside database call", self.make2darray.count)
} //closing function
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.