Reputation: 144
How to wait to return a value after a closure completion.
Example:
func testmethod() -> String {
var abc = ""
/* some asynchronous service call block that sets abc to some other value */ {
abc = "xyz"
}
return abc
}
Now I want the method to return only after xyz
value has been set for variable and not empty string.
How to achieve this?
Upvotes: 8
Views: 5972
Reputation: 285270
Since Swift 5.5 the recommended way is async/await
. If the API doesn't provide an async
version you can create your own with a Continuation
func testMethod() async -> String {
return await withCheckedContinuation({ continuation in
someAsynchronousServiceCallBlock() { result in
continuation.resume(returning: result)
}
})
}
You have to call the mathod in an asynchronous context for example in a Task
Task {
let result = await testMethod()
}
Upvotes: 2
Reputation: 1
Yes, it is possible to wait for the closure function to populate the data and then return the variable. Although, it is suggested to avoid using semaphore to do that, I think that is the only way.
func foo() -> String {
var str = ""
let semaphore = DispathSemaphore(value: 1) //1 if you are waiting for one closure function to signal the semaphore to continue the main thread execution
getAsync() {
//populate the variable
str = "bar"
semaphore.signal()
}
semaphore.wait()
return str
}
Upvotes: 0
Reputation: 968
this is absolutely not possible, because it is just not how asynchronous tasks are working.
what you could do is something like this:
func testmethod(callback: (abc: String) -> Void) {
asyncTask() {
callback(abc: "xyz")
}
}
Have a nice day.
EDIT (for newer Swift Versions):
func testMethod(callback: @escaping (_ parameter: String) -> Void) {
DispatchQueue.global().async { // representative for any async task
callback("Test")
}
}
Upvotes: -5
Reputation: 20720
It is possible (However make sure this is what you really want.).
You have to use something that will block a thread until a resource is available, like semaphores.
var foo: String {
let semaphore = DispatchSemaphore(value: 0)
var string = ""
getSomethingAsynchronously { something in
string = something
semaphore.signal()
}
semaphore.wait()
return string
}
Bare in mind that the thread you are working on will be blocked until the
getSomethingAsynchronously
is done.
Upvotes: 12