'(Swift) How to make async code, synchronously?

I am making an application using Swift.
I want to take data from FireStore, but the problem is that the application goes on to the next job, before finishing retrieving data.
So I tried to use this "DispatchSemaphore" code, but this stops the application from working...
I want to know how to wait the getDocument closure to finish its task, and move to next.

func changeTerms(uniqueName: String) {
        print("colRef: \(colRef.document(uniqueName).path)")
        let semaphore = DispatchSemaphore(value: 0)
        colRef.document(uniqueName).getDocument { snapShot, err in
            if let err = err {
                self.makeAlerts(title: "Error", message: err.localizedDescription, buttonName: "OK")
            } else {
                if let doc = snapShot, doc.exists {
                    if let data = doc.data() {
                        if let terms = data[K.Fstore.data.attributes] as? [String] {
                            var temp: [String] = []
                            for attIdx in self.rankedAttributes {
                                temp.append(terms[attIdx])
                            }
                            self.attributeTerms = temp
                            print("attributeTerms: \(self.attributeTerms)")
                            self.showTitle()
                            self.showTerm()
                        }
                    }
                }
            }
            semaphore.signal()
        }
        semaphore.wait()
    }


Solution 1:[1]

I ran into the same issue with Firebase, and I found the solution using withCheckedContinuation(). You can learn more about it here.

Your code could be:

let temp: [String] = await withCheckedContinuation { continuation in
        colRef.document(uniqueName).getDocument { snapShot, err in
            if let err = err {
                self.makeAlerts(title: "Error", message: err.localizedDescription, buttonName: "OK")
            } else {
                if let doc = snapShot, doc.exists {
                    if let data = doc.data() {
                        if let terms = data[K.Fstore.data.attributes] as? [String] {
                            var temp: [String] = []
                            for attIdx in self.rankedAttributes {
                                temp.append(terms[attIdx])
                            }
                            self.attributeTerms = temp
                            print("attributeTerms: \(self.attributeTerms)")
                            self.showTitle()
                            self.showTerm()
                        }
                    }
                }
            }
            continuation.resume(returning: temp)
        }
}

The execution will wait for the variable temp to get a value, before it moves on.

This is still an asynchronous code, running in the background, but it will run sequentially.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 HunterLion