This post is written for a deeper understanding of Swift concurrency, that is,
async/await
.
I’ve collected information from reliable sources like Apple Developer’s Document, Swift-evolution repository or Swift Language Guide as much as possible, but may contain incorrect information. In that case, please let me know in the comments.
I highly recommend you to read my previous series.
Structured programming paradigm
Concept of structured & unstructured
📒 from Wikipedia
Structured programming is a programming paradigm aimed at improving the clarity, quality, and development time of a computer program by making extensive use of the structured control flow constructs of selection (if/then/else) and repetition (while and for), block structures, and subroutines.
To put it very simply, structured programming means that the codes are executed in the order it’s written, so to speak, procedurally.
Here is example Swift code that implements structured programming.
You can easily notice that the trailing code is executed only when all preceding codes are completed.
When it’s expressed using completion handler pattern, it can be like:
In this case, unlike the first example, completion of the trailing code affects the preceding code. It can be said that the code is designed unstructured.
Swift’s old concurrency codes are unstructured

Before Swift concurrency was introduced, concurrency programming in Swift had to be done mostly in an unstructured way as the example we saw.
Using DispatchQueue
’s async
and Combine
's Publisher
, we’ve had to use a callback function to get the results. Unfortunately, using them, our codes couldn’t help but being written in unstructured way.
Unstructured programming, where the trailing code can affect the preceding code, reverses natural reading order, thus ruining readability and creating error-prone structure.
Due to these reasons, the need for structured code in asynchronous programming in Swift had emerged and as a result, Swift concurrency was proposed.
Structured concurrency in Swift
Structured programming can be said as the core concept of Swift concurrency. You can get a glimpse of makers’ intention from proposal document written in Swift-evolution repository and WWDC session, Explore structured concurrency in Swift — WWDC21.
Now, let’s take a look at differences between structured and unstructured programming in Swift through URLSession
.
First example is the way using completionHandler
, which has been used commonly so far.
It has following features:
- It’s a function receiving callback when the
dataTask
is completed, using a closure,completionHandler
. - In here, you must directly call
completionHandler
to deliver the processed image outside. - In addition to pass the data,
Result
type was used to throw error outside.
Second example is the code using async
/await
, changed from completionHandler
.
It has following features:
- Since data loading is suspended with
await
, all code will stop at that point until the operation is completed. - When the operation’s done, the result data will be saved in the variable
data
. - Now code will resume from the suspension point and then creates an image with the data. After that, task returns image.
As you saw, code will be executed in the order in which it’s written, which can be said structured.
Comparison

In the first example, using completionHandler
, it has a problem that result can not be passed if someone forgot to call completionHandler
. It’s one of the common problems code using completion handler pattern has.
However, in the second example, using async
/await
, result is passed without using completionHandler
, so potential errors it has disappear.
Also, no need for using Result
type, you can throw an error right away using the keyword try
. Using throw
is also allowed.
Thanks to all of these features, code becomes more shorter and legible, in addition to get some improvement of performance.
Task?
By the way, we’ve used the keyword Task
unconsciously.
In a nutshell, Task
is a unit of async job in Swift concurrency and its initializer helps making unstructured concurrency in Swift concurrency’s context.
Okay, it seems right time to dig deeper into the Task
.