skip to Main Content

I have a async function func doWork(id: String) async throws -> String. I want to call this function from a concurrent dispatch queue like this to test some things.

for i in 1...100 {
    queue.async {
        obj.doWork(id: "foo") { result, error in 
          ...
        }
    }
}

I want to do this because queue.async { try await obj.doWork() } is not supported. I get an error:

Cannot pass function of type ‘@Sendable () async throws -> Void’ to parameter expecting synchronous function type

But the compiler does not provide me with a completion handler version of doWork(id:). When I call it from Obj C, I am able to use the completion handler version: [obj doWorkWithId: @"foo" completionHandler:^(NSString * val, NSError * _Nullable error) { ... }]

How do I do something similar in Swift?

2

Answers


  1. You can define a DispatchQueue. This DispatchQueue will wait for the previous task to complete before proceeding to the next. 

    let queue = DispatchQueue(label: "queue")
    
    func doWork(id: String) async -> String {
        print("Do id (id)")
        return id
    }
    
    func doWorksConcurrently() {
        for i in 0...100 {
            queue.async {
                Task.init {
                    await doWork(id: String(i))
                }
            }
        }
    }
    
    doWorksConcurrently()
    
    Login or Signup to reply.
  2. You are initiating an asynchronous task and immediately finishing the dispatch without waiting for doWork to finish. Thus the dispatch queue is redundant. One could do:

    for i in 1...100 {
        Task {
            let results = try await obj.doWork(id: "foo")
            ...
        }
    }
    

    Or, if you wanted to catch/display the errors:

    for i in 1...100 {
        Task {
            do {
                let results = try await obj.doWork(id: "foo")
                ...
            } catch {
                print(error)
                throw error
            }
        }
    }
    

    Now, generally in Swift, we would want to remain within structured concurrency and use a task group. But if you are trying to mirror what you’ll experience from Objective-C, the above should be sufficient.

    Needless to say, if your Objective-C code is creating a queue solely for the purpose for calling the completion-handler rendition of doWork, then the queue is unnecessary there, too. But we cannot comment on that code without seeing it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search