Your Table View Cell Shows the Wrong Image. The Network Call Was Right — The Cell Just Wasn't.
UITableView and UICollectionView reuse cell views to stay fast, but an async image load or network callback that fires after a cell has been recycled writes into the wrong row. Here's why it happens, why it's so hard to reproduce, and the three fixes that actually close it.
A Continuation Can Only Be Resumed Once. Swift Won't Stop You From Trying Twice.
withCheckedContinuation bridges callback-based APIs into async/await, but resuming it twice crashes at runtime and resuming it zero times hangs forever — and the compiler catches neither. Here's the failure shape and the fix.
Task.detached Isn't Task With Extra Steps. It Throws Away Everything Task Inherited For You.
Task.detached in Swift concurrency looks like a stronger version of Task, but it silently drops actor isolation, priority, and task-local values. Here's what actually breaks, and when detached is genuinely the right call.
SwiftUI's .task(id:) Cancels for You. .onChange Doesn't. That Gap Is Where Your Duplicate Network Calls Live.
.task(id:) and .onChange(of:) both react to a value changing, but only one of them cancels the work it started. Here's the SwiftUI concurrency gotcha that ships silently duplicate requests.
An Actor Isn't a Lock. It's a Line With a Very Specific Rule About Cutting.
Swift actors guarantee that only one task touches their state at a time — except across every await, where a second task can walk right in. Here's what actor reentrancy actually means and the bug pattern it causes.
SwiftUI Cancels Your .task When the View Disappears. Your await Doesn't Get the Memo.
SwiftUI's .task modifier automatically cancels its Task when a view disappears — but cancellation is cooperative, not magic. Here's why your network call keeps running anyway, and the three checks that actually stop it.
The Actor That Refreshes Your Token Perfectly. It Also Forgets It on Relaunch.
AuthTokenStore solved the token-refresh race condition with a Swift actor. What it never solved is where the token lives between launches. Here's why an in-memory actor isn't secure storage, and what a Keychain-backed version actually costs you.
Your @MainActor Code Was Never Promised the Main Thread. Swift's About to Make That Official.
Swift Evolution's fourth pitch for Custom Main and Global Executors quietly confirms something most iOS developers get wrong: @MainActor guarantees serialized isolation, not literally Thread.main. Here's what changes and why it matters.
Swift Wants to Let a Closure Promise 'I Run Once.' Here's the Bug That's Been Waiting For It.
A fresh Swift Evolution pitch, @called(once), lets the compiler know a function is invoked at most one time — and that one guarantee quietly unlocks Task closures that consume non-Sendable values and non-Copyable captures that don't work today. Here's the errors it fixes, in real code.
Typed Throws in Swift 6: A Real Migration, and the Wall It Hits at a Protocol
Swift 6's typed throws (throws(SomeError)) let you catch errors exhaustively without a default case. Applied to BrewLog's real NetworkClient, here's what actually improves — and the protocol boundary where typed throws quietly stops helping.
ST-0026 Got Accepted. The Whole Review Came Down to One Parameter Label.
Swift Testing's .taskLocal trait (ST-0026) was accepted with modifications on August 15, 2026 — the only change was adding a withValue: label. Here's the final API, why the label debate actually mattered, and the real BrewLog migration it unlocks.
Weak Self Isn't the Retain Cycle Fix You Think It Is in @Observable
The old [weak self] advice was written for closures capturing classes. @Observable changes what actually gets captured, and in a few common SwiftUI patterns weak self silently does nothing at all. Here's where it still matters and where it's dead weight.
Swift Testing Runs Your Suite in Parallel. That Static Var You Swap for DI Is a Race Condition.
Swift Testing parallelizes tests by default, in the same process. A huge number of Swift codebases — BrewLog's AppIntents suite included — still inject test dependencies by mutating a global static var. ST-0026 proposes a .taskLocal trait to fix it properly. Here's the real bug, the real code, and where the proposal stands.
Swift Just Got a Real Timeout API. Here's What We've All Been Duct-Taping Instead.
SE-0526 withDeadline was accepted into Swift on July 30, 2026 — a real, composable, absolute-time-limit API for async operations. I found the exact gap it fills in a real app's networking layer, fixed it today's way with a TaskGroup race, and lined it up against what withDeadline will let me delete once it ships.
Retry, Token Refresh, and Request Deduplication in Swift
Day 23 of the 30-day iOS series. The three production concerns every 'build your own networking layer' tutorial skips, built as composable actors on top of Day 22's client — plus a real concurrency bug I found writing the test, not the code.
Swift Has 217 Keywords Now. Nobody Agrees on What It's For.
Swift started as a simple, elegant language that composed beautifully. Twelve years later, it has 217 keywords, a governance problem, and an identity crisis. With WWDC 2026 weeks away, the community is asking: is Apple killing its own programming language?
WWDC 2026 Is 26 Days Away. This Is Your iOS Developer Pre-Flight Checklist.
WWDC 2026 lands June 8. SiriKit deprecation, Core AI replacing Core ML, Liquid Glass refinements, foldable iPhone APIs, and strict concurrency in Swift 7. Here's the practical pre-flight checklist to run through your codebase right now — before the keynote makes it urgent.