Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Syntax to wrap a completion handler in dispatch async

I have a completion handler that I need to assign to a property, but I want it to execute asynchronously.

If I didn't have that requirement, I would write:

request.completionBlock = completionBlock

But since I have this requirement, I have to write this

request.completionBlock = { response, error in
  DispatchQueue.main.async {
    completionBlock(response, error)
  }
}

which seems redundant and un-swifty.

Isn't there some easier syntax? I would like to write something like

request.completionBlock = completionBlock.map(DispatchQueue.main.async)

Can I express my need in such a simple way?

like image 857
KPM Avatar asked Nov 26 '25 10:11

KPM


2 Answers

There isn't a built-in syntax for expressing that, but you can always define a generic function or operator to enable something along those lines.

For example:

infix operator >

func ><T>(left:@escaping (T)->(), right:DispatchQueue) -> (T)->() {
  return { input in
    right.async { left(input) }
  }
}

With the above custom operator defined, your code can be:

request.completionBlock = completionBlock > DispatchQueue.main

which I think is the general feel you are looking for.

like image 158
Daniel Hall Avatar answered Nov 27 '25 22:11

Daniel Hall


Here is an extension

extension DispatchQueue {
    func asyncClosure<T>(_ closure:@escaping (T) -> Void) -> (T) -> Void {
        return {i in self.async {closure(i)}}
    }
}

that allows you to do this:

request.completionBlock = DispatchQueue.main.asyncClosure(completionBlock)
like image 44
bzz Avatar answered Nov 28 '25 00:11

bzz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!