Reputation: 682
I'm new in async stuff in swift, ans I'm trying to implement a simple async call to a function.
import UIKit
func doAsyncStuff ( completionHandler: (_ result: Double) -> Void) {
print("start async")
sleep(5) // to simulate long work
let result: Double = 123.456
completionHandler(result)
}
print("A")
doAsyncStuff() { result in
print(result)
}
print("B")
When I execute it, I get
A
start async
123.456
B
As the func is called asynchronously, I would have expected to get
A
start async
B
123.456
Where did I go wrong ? Thanks a lot
Upvotes: 1
Views: 331
Reputation: 4411
Your function is not asynchronous. Each line of code is being run synchronously (i.e. waiting for the line before to complete before executing). So the sleep(5) pauses execution in the middle of the function and print("B") is not called until after the function returns.
You can use Grand Central Dispatch (GCD) to run code asynchronously on a different thread. Here is an example:
import UIKit
func doAsyncStuff ( completionHandler: (_ result: Double) -> Void) {
DispatchQueue.global(qos: .background).async { [weak self] in
print("start async")
sleep(5)
let result: Double = 123.456
completionHandler(result)
}
}
print("A")
doAsyncStuff() { result in
print(result) // This is your completion handler code
}
print("B")
Upvotes: 2
Reputation: 280
Use DispatchQueue.main.asyncAfter for an asynchronous call in swift. So your code should look like..
func doAsyncStuff ( completionHandler: (_ result: Double) -> Void) {
print("start async")
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
// your code goes from here
let result: Double = 123.456
completionHandler(result)
}
}
Upvotes: 1
Reputation: 6922
Beware, you are calling your function on the same thread, therefore it will be synchronous!
To call it in an asynchronous fashion, create a background thread/task, and call your function from that background thread. One way of doing it:
print("A")
DispatchQueue.global(qos: .background).async {
//this is a background thread, do in it your async stuff
doAsyncStuff() { result in
print(result)
}
}
print("B")
Upvotes: 1
Reputation: 54795
The issue is that you're calling sleep
, which is a synchronously blocking function, so you block the main thread for 5 seconds and nothing else can be executed in the meantime. You should use DispatchQueue.asyncAfter
to test simple async calls.
You can also know that your function is not asynchronous, since you didn't receive a compiler error for not marking your closure as @escaping
, which you need to do for async completion handlers.
func doAsyncStuff(completionHandler: @escaping (_ result: Double) -> Void) {
print("start async")
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
completionHandler(123.456)
}
}
Upvotes: 3