0

I have tried to move things around but my call to my database in cloud firestore is returning a nil for some reason. I have data in the database, and triple checked the relation but can't seem to find why it's acting the way it is.

Here is my code for the function:

func getAllTasks() -> [String: Any] {
        db = Firestore.firestore()
        
        var customers : [String: Any]!
        
        
        db.collection("CustomerCollection").whereField("uploaded", isEqualTo: true)
            .getDocuments() { (querySnapshot, err) in
                if let err = err {
                    print("Error getting documents: \(err)")
                } else {
                    for document in querySnapshot!.documents {
                        print("\(document.documentID) => \(document.data())")
                        customers = document.data()
                    }
                }
        }
        
        return customers
    }

When this is called the error is at the .getDocuments part, it is underlined and the error states: "Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value"

Here is my database as well

Database

lduell
  • 1
  • 2
  • If you search the error you’ll find plenty of solutions. You shouldn’t use “!”. Your snapshot is nil for some reason it could be permissions, check your console. – lorem ipsum Aug 25 '23 at 12:26
  • Permissions should be fine, I have a login established with permissions to read and write with given auth. I've also been able to write in my other functions. If I use "!" where would I put it? I tried using it before and wasn't exactly sure where to put it since the function .getDocuments() is returning the nil. I've also done a good days worth of research on this error and haven't been able to find a solid solution. I'm also using exactly what firestore says to use in their documentation with my own collection and field – lduell Aug 25 '23 at 12:39
  • Look at [this](https://stackoverflow.com/questions/73429625/how-to-infer-a-generic-paramater-with-an-async-await-function/73430225#73430225) code it is a newer version. You are also expecting synchronous results with an asynchronous operation. – lorem ipsum Aug 25 '23 at 12:43
  • Ding! Ding! Ding! Thank you for your help, that article helped a lot. I need to understand what the heck I just wrote though before I move forward lol. – lduell Aug 25 '23 at 15:18
  • Does this answer your question? [How to infer a generic paramater with an async/await function](https://stackoverflow.com/questions/73429625/how-to-infer-a-generic-paramater-with-an-async-await-function) – lorem ipsum Aug 25 '23 at 16:50

1 Answers1

1

Data is loaded from Firestore (and most Cloud APIs) asynchronously, as it may take some time.

Instead of blocking the app, your main code (including the return customers) continues to execute while the data is being loaded. Then when the data is available, your closure is called and executes the customers = document.data().

So your getAllTasks returns nil, because it completes before all the data has loaded. There is no way to make it wait for the data to be loaded, as that would block the UI. All code that needs to data has to be inside the getDocuments closure, be called from there, or be otherwise synchronized.

You'll have to pass in a closure to getAllTasks, pretty much the same as the closure you pass to getDocuments and call that once the data is available.

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807