简体   繁体   中英

Getting empty Array from Firestore Function (swift)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM