How can I get the return value from an asynchronous dispatch block?
I came up with this example code:
if let url = URL(string: "https://google.com/") {
let data: Data? = ***SOME_ASYNC_AWAIT_DISPATCH_GROUP<T>*** { return try? Data(contentsOf: url) }
print("Downloaded Data: \(data)")
}
Goal: Here, I want the async call to produce a result and store it to the data
constant so that I can use it.
I am simple using the completion method to do this. Test function download the data from url in background thread and after downloading the completion block run, it returns downloaded data, it may in any formate convert it in your formate.
func UpdateUI(){
test { (data) in
//data is value return by test function
DispatchQueue.main.async {
// Update UI
//do task what you want.
// run on the main queue, after the previous code in outer block
}
}
}
func test (returnCompletion: @escaping (AnyObject) -> () ){
let url = URL(string: "https://google.com/")
DispatchQueue.global(qos: .background).async {
// Background work
let data = try? Data(contentsOf: url!)
// convert the data in you formate. here i am using anyobject.
returnCompletion(data as AnyObject)
}
}
Hope it will help you.
I found a solution.
// REFERENCED TO: https://gist.github.com/kylesluder/478bf8fd8232bc90eabd
struct Await<T> {
fileprivate let group: DispatchGroup
fileprivate let getResult: () -> T
@discardableResult func await() -> T { return getResult() }
}
func async<T>(_ queue: DispatchQueue = DispatchQueue.global() , _ block: @escaping () -> T) -> Await<T> {
let group = DispatchGroup()
var result: T?
group.enter()
queue.async(group: group) { result = block(); group.leave() }
group.wait()
return Await(group: group, getResult: { return result! })
}
Call to like this.
let data = async{ return try? Data(contentsOf: someUrl) }.await()
OR
More simple:
@discardableResult func async<T>(_ block: @escaping () -> T) -> T {
let queue = DispatchQueue.global()
let group = DispatchGroup()
var result: T?
group.enter()
queue.async(group: group) { result = block(); group.leave(); }
group.wait()
return result!
}
Call to like this.
let data = async{ return try? Data(contentsOf: someUrl) }
(And thanks for edit my question, Seaman.)
This should work with a sync block
var result:T? = nil
DispatchQueue.global(qos: .background).sync {
//Do something then assigne to result
}
return result
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With