I am facing an issue in using semaphores on iOS. I am implementing a feature to execute a series of async methods sequentially, one after another in order.
let semaphore = DispatchSemaphore(value: 1)
semaphore.wait()
performFirstTask {
semaphore.signal
}
semaphore.wait()
performSecondTask {
semaphore.signal
}
semaphore.wait()
performThirdTask {
semaphore.signal
}
So this is working as expected, but the issue comes if the user moves away from the screen in the wait state, so when the callback from a particular task fires, the view might have deallocated, which is causing a crash, Can anyone please help me to resolve this issue, I am not seeing any way to release the semaphores.
Thanks in advance
Let us imagine that you decided to adopt Swift concurrency, rather than using semaphores. So, what would this look like with async
-await
?
Let us imagine for a second that you refactored performFirstTask
, performSecondTask
, and performThirdTask
to adopt Swift concurrency. Then, you eliminate the semaphore completely, and your fifteen lines of code are reduced to:
Task {
await performFirstTask()
await performSecondTask()
await performThirdTask()
}
That performs those three asynchronous tasks sequentially, but avoids all of the downsides of semaphores. The whole idea of async
-await
is that you can represent dependencies between a series of asynchronous tasks very elegantly.
Now, generally you would refactor the performXXXTask
methods to adopt Swift concurrency. Alternatively, you could also just write async
“wrapper” functions for them, e.g.:
func performFirstTask() async {
await withCheckedContinuation { continuation in
performFirstTask() {
continuation.resume(returning: ())
}
}
}
That is an async
rendition of performFirstTask
that calls the completion handler rendition.
However you decide to do it (refactor these three methods or just write wrappers for them), Swift concurrency simplifies the process greatly. See WWDC 2021 video Swift concurrency: Update a sample app for more examples about how to convert legacy code to adopt Swift concurrency.