§ · napkin journal
Notes from the smokehouse.
Posts on Swift 6 concurrency, iOS app architecture, dependency injection, actor testing, and the design choices behind napkin.
-
The Swift 6 @MainActor listener-conformance error, and a seam that sidesteps it
"Main actor-isolated property 'listener' cannot be used to satisfy nonisolated protocol requirement" is the error every RIB-shaped listener seam hits under Swift 6. Why it happens, and the whole-protocol @MainActor design that makes it structurally impossible.
Read -
A RIBs alternative for Swift Concurrency, without RxSwift: meet napkin
Uber's RIBs is alive, well, and actively developed. It's also built on RxSwift and ships a runtime leak detector. napkin is the same Router-Interactor-Builder pattern written for Swift Concurrency, without either — Clean Architecture on a napkin.
Read -
Actor isolation for iOS app architecture in Swift 6
Swift 6 makes you declare where every piece of code runs. That's an architecture decision in disguise. Here's the four-ring isolation map napkin uses and why business logic belongs off the main actor.
Read -
Dependency injection in SwiftUI without third-party libraries
SwiftUI's
Read@Environmentwasn't designed for services, and@EnvironmentObjectcrashes at runtime when you forget. There's a third option that's been around since RIBs and works cleanly with actors. -
Testing Swift actors: a practical guide
If your business logic is in
Readfinal actortypes, you can unit-test it without a simulator. Mock the protocols, drive the lifecycle, assert on recorded calls. Here's the pattern, with examples. -
Modular iOS apps with Swift Concurrency
Modularity isn't a build-system question. It's about whether features can be reasoned about in isolation. Here's how to compose an iOS app as a tree of small, isolated units in Swift 6 — no module-graph gymnastics required.
Read