Member-only story
Structured vs. Unstructured Concurrency in Swift
You fire an async API call… the view disappears… but the task is still running.
Alok Upadhyay9 min read·1 hour ago--
👉 “You can read the full article here (no membership needed).”
You tap a button. A loading spinner appears. You fire an async network call to fetch a massive payload of high-res images. Half a second later, the user changes their mind, swipes back, and the view controller deallocates.
The screen is gone. The user has moved on. But deep in the background, your network request is still grinding away — silently burning battery, chewing through the user’s data plan, and perhaps even preparing to crash your app when it finally returns and tries to update a UI that no longer exists.
This is the dark side of modern app development. For years, we’ve been firing and forgetting. But concurrency without control isn’t a feature; it’s a memory leak waiting to happen.
The Old World: The Wild West of Unstructured Tasks
Before Swift concurrency matured, we relied heavily on Grand Central Dispatch (GCD) and escaping closures. We dispatched work to background queues and crossed our fingers that the state would be valid when the callback finally fired.