[Book Update] Async Chapter Revision Based On Feedback + Chapter Conclusion
Thank you everyone for your feedback on the async chapter! It helped me a lot to polish it! Also, wanted to share the conclusion of the chapter here on substack.
Thank you everyone who responded to my call for feedback on the async chapter of The iOS Interview Guide 2nd edition!
I’ve added several major sections based on your input:
Continuations for bridging legacy APIs - How to wrap old completion handler code into async/await using
withCheckedContinuation. This was a big omission since basically every real codebase needs to bridge between old and new async patterns.Actor reentrancy solutions - Added the pattern for fixing reentrancy bugs. Shows how concurrent callers can await the same task instead of creating race conditions.
Debounced search with Task cancellation - Practical example of search bar implementation showing how to store task handles, cancel them on new input, and use
Task.sleepfor debouncing. Includes both async/await and RxSwift versions since that’s what you’ll actually encounter in production code.Network request comparison across all paradigms - This was the biggest addition. Same user profile fetch implemented four ways: completion handlers, async/await, Combine, and RxSwift. All using a unified APIClient with proper Swift 6 concurrency compliance. Interviewers love asking this type of question because it shows you understand the trade-offs between approaches, not just the latest Apple marketing.
And here’s how the chapter concludes - my take on async work in iOS:
Async work on iOS has evolved from manual threads to GCD to reactive frameworks to Swift Concurrency. Each approach solved real problems for its time.
Here’s what the industry expects: Swift Concurrency is the default for new code. If you’re interviewing or joining teams building new features, expect async/await, actors, and structured concurrency everywhere. You need to know it cold. That said, production codebases have years of existing code - you’ll maintain GCD dispatches, RxSwift chains, Combine publishers. Real work means bridging all these paradigms.
Here’s my actual opinion though: Rx (whether RxSwift, RxJS, or RxJava) is a superior model for asynchronous code. It handles simple cases just as well as async/await, but gives you real power for complex reactive flows. More importantly, learning Rx once translates across every platform and language - your RxSwift knowledge works in RxJS, RxJava, RxKotlin. That portability matters.
Apple’s attempt to eliminate concurrency bugs through Swift Concurrency sounds great on paper, but the infuriatingly strict compiler constraints often do more harm than good. That’s not elegant - that’s fighting the compiler to do reasonable things.
If you have solid architecture, most concurrency problems disappear. When your application state, domain models, and UI layer are clearly separated, when you avoid global state and singletons, race conditions become rare. The bugs Swift Concurrency tries to prevent at compile time just don’t happen in well-architected apps.
So my message to mobile engineers: don’t obsess over using the most recent stuff just because Apple said so. Focus on getting your architecture right. Avoid singletons and global state. Once you have clean separation of concerns, the async code becomes easy regardless of which tool you pick.
Know Swift Concurrency because you’ll be asked about it in interviews. Understand GCD and reactive patterns for maintenance work. But don’t treat any of these as religion - they’re tools. Pick what fits your problem and your architecture.
The comparison patterns in the chapter - especially the network request implementations across all four paradigms - show how the same problem gets solved differently. Use them as templates when evaluating which approach fits your specific situation.

