user3116871
user3116871

Reputation: 333

Wait for query to fetch Firestore data before continue

I would like to fetch the user/author of the article into a computed property. But this never happens, below code would print 1, 2, 4.

struct Article {
    private let database = Firestore.firestore()

    var authorId: String
    var message: String

    var author: User? {

        print(1)
        var fetchedAuthor: User?
        let semaphore = DispatchSemaphore(value: 0)

        print(2)
        database.collection("users").document(authorId).getDocument { (document, error) in

            print(3)
            guard let user = document.flatMap({User(dictionary: $0.data())}) else {
                print("Could not get author: \(error.debugDescription)")
                semaphore.signal()
                return
            }

            fetchedAuthor = user
            semaphore.signal()
        }

        print(4)

        semaphore.wait()
        print(5)
        return fetchedAuthor
    }
}

Upvotes: 1

Views: 2572

Answers (2)

AgRizzo
AgRizzo

Reputation: 5271

Adding pseudo/ sample code to the comment by @Connor, since I just went through this.

extension User {
  static func getBy(documentID id: String, completion: @escaping (User)->()) {
    database.collection("users").document(id).getDocument { (document, error) in
        guard let user = document.flatMap({User(dictionary: $0.data())}) else {
            print("Could not get author: \(error.debugDescription)")
            return
        }
        completion(user)
  }
}

Then in your Article struct:

struct Article {
  ....
  init(){
    ....
    // Get the user
    User.getBy(documentID: self.userID) { user in
      self.author = user
    }
  }
}

Upvotes: 1

sschunara
sschunara

Reputation: 2285

semaphore.wait() //is for requesting the resource(semaphore)
semaphore.singal() //is for releasing the resource(semaphore)

Change code as per below.

var author: User? {

        print(1)
        var fetchedAuthor: User?
        let semaphore = DispatchSemaphore(value: 1)

        print(2)
        database.collection("users").document(authorId).getDocument { (document, error) in
            semaphore.wait()
            print(3)
            guard let user = document.flatMap({User(dictionary: $0.data())}) else {
                print("Could not get author: \(error.debugDescription)")
                return
            }

            fetchedAuthor = user
            semaphore.signal()
        }

        print(4)
        print(5)
        return fetchedAuthor
    }

Upvotes: 0

Related Questions