Search code examples
iosswiftasynchronousasync-await

How to make async / await in Swift?


I would like to simulate async and await request from Javascript to Swift 4. I searched a lot on how to do it, and I thought I found the answer with DispatchQueue, but I don't understand how it works.

I want to do a simple stuff:

if let items = result.value {
    var availableBornes = [MGLPointFeature]()

    for item in items {
        guard let id = item.id else { continue }

        let coordinate = CLLocationCoordinate2D(latitude: Double(coor.x), longitude: Double(coor.y))

        // ...

        // This is an asynchronous request I want to wait
        await _ = directions.calculate(options) { (waypoints, routes, error) in
            guard error == nil else {
                print("Error calculating directions: \(error!)")
                return
            }

            // ...

            if let route = routes?.first {
                let distanceFormatter = LengthFormatter()
                let formattedDistance = distanceFormatter.string(fromMeters: route.distance)
                item.distance = formattedDistance

                // Save feature
                let feature = MGLPointFeature()

                feature.attributes = [
                    "id": id,
                    "distance": formattedDistance
                ]

                availableBornes.append(feature)

            }
        }
    }

    // This should be called after waiting for the async requests
    self.addItemsToMap(availableBornes: availableBornes)
}

What should I do?


Solution

  • Thanks to vadian's comment, I found what I expected, and it's pretty easy. I use DispatchGroup(), group.enter(), group.leave() and group.notify(queue: .main){}.

    func myFunction() {
        let array = [Object]()
        let group = DispatchGroup() // initialize
    
        array.forEach { obj in
    
            // Here is an example of an asynchronous request which use a callback
            group.enter() // wait
            LogoRequest.init().downloadImage(url: obj.url) { (data) in
                if (data) {
                    group.leave() // continue the loop
                }
            }
        }
    
        group.notify(queue: .main) {
            // do something here when loop finished
        }
    }