neo
neo

Reputation: 164

Swift function to return documents from Firestore

Update 2:

Got this thing to work. Not as elegant as I expected, but works.

The final func is this:

func fetchData(completion: @escaping ([MyModel]?) -> Void) {
    
    self.db
        .collection("data/userData")
        .order(by: "modified", descending: true)
        .addSnapshotListener { querySnapshot, error in
            guard let documents = querySnapshot?.documents else {
                print("no documents \(String(describing: error))")
                completion(nil)
                return
            }
          let result = documents.compactMap { queryDocumentSnapshot -> MyModel? in
                return try? queryDocumentSnapshot.data(as: MyModel.self)
            }
            completion(result)
        }

}

Calling it like this:

fetchData() { arr in if arr != nil {
                //Attach it to vars or whatever
            }}

I'm accepting @workingdog answer.


Update 1: Edit: Following @workingdog comment, I tried using this code:

func fetchMyData(completion: @escaping ([MyModel]?) -> Void) {
self.db
    .collection("data/userData")
    .order(by: "modified", descending: true)
    .addSnapshotListener { [self] querySnapshot, error in
        guard let documents = querySnapshot?.documents else {
            print("no documents \(String(describing: error))")
            completion(nil)
            return
        }
      let result = documents.compactMap { queryDocumentSnapshot -> MyModel? in
            return try? queryDocumentSnapshot.data(as: MyModel.self)
        }
        completion(result)
    }

}

This does still not give me a solution as I'm trying to call this method from a different function but it crashes my app. But also, I only wanted to call it with "var myDocuments = fetchData()". The above code doesn't give me that (although I'm not even sure what I'm asking is possible).


I have this code/query that should return documents from Firestore:

func fetchMyData() {
    
    self.db
    .collection("data/userData")
    .order(by: "modified", descending: true)
        .addSnapshotListener { [self] querySnapshot, error in
        guard let documents = querySnapshot?.documents else {
            print("no documents \(String(describing: error))")
            return
        }
        
        print(documents.compactMap { (queryDocumentSnapshot) -> MyModel? in
            return try? queryDocumentSnapshot.data(as: MyModel.self)
        })
        
    }
    
}

I want this function to return the results instead of printing them. I tried to push them into a high-level variable (self.myDocuments) but this is no good when the project becomes bigger and lots of other functions try to run this query for their own needs.


I tried using:

return documents.compactMap { (queryDocumentSnapshot) -> MyModel? in
            return try? queryDocumentSnapshot.data(as: MyModel.self)
        }

But got this error message:

Unexpected non-void return value in void function

I understand that 'compactMap' can't return anything, but what else can I do to grab these documents and have 'fetchMyData' to return them?

Upvotes: 0

Views: 328

Answers (1)

if "I want this function to return the results instead of printing them." means you expect one MyModel, then try something like this:

EDIT: returning an optional array of MyModel:

func fetchMyData(completion: @escaping ([MyModel]?) -> Void) {
    self.db
        .collection("data/userData")
        .order(by: "modified", descending: true)
        .addSnapshotListener { [self] querySnapshot, error in
            guard let documents = querySnapshot?.documents else {
                print("no documents \(String(describing: error))")
                completion(nil)
                return
            }
            let result = documents.compactMap { queryDocumentSnapshot -> MyModel? in
                return try? queryDocumentSnapshot.data(as: MyModel.self)
            }
            completion(result)
        }
}

use it like this:

    fetchMyData() { results in
        if let modelArray = results {
            // do something with your [MyModel] modelArray
        }
    }

Upvotes: 2

Related Questions