Your Timer Stops Every Time the User Scrolls. Timer Is Working Exactly as Documented.
A scheduled Timer silently stops firing the moment a user touches a scroll view, because scheduledTimer adds itself to the run loop's default mode and scrolling switches to tracking mode. Here's the mechanism, and why reaching for .common isn't automatically the right fix.
Your Crash Rate Doubled Overnight. You Didn't Ship Anything.
A third-party SDK can crash your already-shipped iOS app without you releasing a single line of code. Here's the mechanism behind server-driven SDK crashes, why pinning your dependency versions doesn't protect you, and the kill switch you need to ship before you need it.
SwiftUI's Purple Warning Isn't Cosmetic. 'Publishing Changes From Within View Updates' Means You Raced Your Own Render.
Xcode's console warns 'Publishing changes from within view updates is not allowed, this will cause undefined behavior' and most developers just scroll past it. Here's what SwiftUI is actually telling you, the three common ways you trigger it, and why ignoring it eventually costs you a view that won't stop re-rendering.
You Can Mutate an Object Sitting Inside a Set. Swift Won't Stop You. It Should Terrify You.
Swift's Set and Dictionary assume a value's hash never changes after you insert it. Mutate a class instance that's already stored in one, and the collection silently corrupts — contains() returns false for an object you can see right there when you iterate. Here's why, and how to actually avoid it.
SwiftUI's .onAppear Doesn't Mean 'First Appearance.' It Means 'Any Appearance.'
onAppear fires every time a SwiftUI view becomes visible again, not just once — including every time you pop back to it in a NavigationStack. Here's why that duplicates network calls and how to fix it with .task(id:) or a one-shot flag.
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.
Thread Sanitizer Just Flagged Your Correct Code as a Race. Swift Might Finally Let You Say 'I Know.'
SE-0550 proposes a @noSanitize attribute for Swift functions, letting you opt individual functions out of ASan/TSan instrumentation. Here's the real problem it solves, and the sharp edges it comes with.
Codable's Snake Case Conversion Looks Like Free API Mapping. It Breaks on the First Acronym.
JSONEncoder's .convertToSnakeCase and JSONDecoder's .convertFromSnakeCase promise to erase the naming gap between Swift and your API. They do — right up until a property has an acronym in it, and then they fail silently on Optional fields instead of throwing.
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.
Your defer Didn't Fire Late. It Fired Exactly on Time — Just Not the Time You Meant
Swift's defer runs at the end of the enclosing scope, not the end of the function. Inside an if/else branch, that difference can silently defeat the cleanup you thought you wrote.
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.
SwiftUI Reset My State for No Reason. The Bug Was Identity, Not Bindings.
A text field kept clearing itself on every re-render, and no amount of staring at @State fixed it. The actual cause was SwiftUI's view identity system silently deciding my view was a brand new one. Here's how identity actually works and the three ways to break it.
Your Background Task Isn't Broken. iOS Just Decided It Wasn't Worth Running.
BGTaskScheduler doesn't promise your task will run — it's a request, scored against battery, usage patterns, and network state. Here's how the budget actually works, how to test it without waiting three days, and how to design a sync that survives never being called.
Apple's On-Device Speech API Reserves Five Locale Slots. You Never Get Them Back.
A developer who actually shipped an app on SpeechTranscriber and Foundation Models found that AssetInventory.release(reservedLocale:) doesn't release anything. I checked Apple's own docs against the bug report, and the gap between what's documented and what happens on a real device is the whole story.
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.
A 16-Year-Old SQLite Bug Just Surfaced. Your SwiftData App Is Sitting on the Same Engine.
Tailscale spent six months and 19 database corruptions tracking down the SQLite WAL-Reset bug, unfixed since 2010 and patched in 3.51.3. SwiftData and Core Data both run on SQLite in WAL mode — so I checked which version iOS 26.2 actually ships, and what it means for your app.