www.loopwerk.io
Thoughts on Apple, and why I left iOS development behind - Loopwerk
Excerpt
But over the years, that initial simplicity and focus have been buried under layers of ever-increasing complexity. It feels like the language sprinted from a practical tool for building apps to a highly academic exercise in language theory. The turning point for me began around Swift 5.5. The introduction of `async`/`await` was a welcome and long-overdue addition, simplifying asynchronous code. But it didn’t come alone. It brought with it the actor model, Structured Concurrency, and a whole new set of rules to memorize. Suddenly, simple background tasks required wrestling with a complex system. Then came the real friction: `@Sendable` and the strict data-race protections. While noble in their goal, in practice they often lead to a demoralizing battle with the compiler. You spend less time building features and more time trying to appease the type checker, deciphering alien error messages about a type not conforming to Sendable. The language that once felt like a helpful partner now felt like a pedantic adversary. ``` // What you want: func doThing() { thing() } // What Swift 6 demands: @MainActor nonisolated(unsafe) func doThing() async throws -> sending some Sendable { await withCheckedThrowingContinuation { continuation in Task { @MainActor in // 47 compiler warnings later } } } ``` This trend continued. Features like property wrappers and result builders, while powerful, added layers of “magic” that obscured what was actually happening. And the recent introduction of macros feels like the final departure from Swift’s original promise of clarity. The code on the screen is no longer the code that runs; it’s a template for generating other code, demanding a whole new level of mental gymnastics to debug and maintain. Each new feature added power, yes, but at the cost of immense cognitive overhead. The language that once empowered the solo developer now feels tailored to large, specialized teams who can afford to have experts in its arcane corners. The joy was gone, replaced by burnout. I still haven’t updated Saga, my static site generator written in Swift, to use Swift 6. I just can’t be bothered, to be honest.
Related Pain Points
Language complexity and cognitive overhead from advanced features
7Swift has evolved from a practical, simple language into an academic exercise with layers of complexity. Features like async/await, actors, structured concurrency, @Sendable, property wrappers, result builders, and macros have created massive cognitive overhead, turning the language from a helpful partner into a "pedantic adversary" that demands extensive boilerplate and compiler appeasement rather than enabling feature development.
Incomprehensible compiler error messages for type constraints
6The @Sendable and strict data-race protections generate cryptic compiler error messages about types not conforming to Sendable, creating a demoralizing battle with the type checker. Developers spend more time deciphering "alien error messages" than building features.
Macros are confusing and error-prone
5Macros are powerful but extremely tempting to misuse, especially for newcomers. They remain widely used throughout codebases despite their difficulty and propensity to introduce hard-to-find bugs.