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.
@AppStorage Looked Like Free State Management. It Isn't Watching What You Think.
@AppStorage feels like @State that happens to persist. It's actually a thin wrapper over UserDefaults with a KVO bridge bolted on, and that difference bites the moment a widget, an app extension, or a background task touches the same key.
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.
@State, @Bindable, @Environment: The Complete Map for @Observable (and the Question You're Actually Asking)
Day 12 of the 30-day iOS series. With @Observable, SwiftUI lets you slap @State, @Bindable, @Environment, or a plain let on the same class — and compiles all of them. Here's the question that actually decides which one is correct, one map that resolves 95% of the confusion, and three real BrewLog bugs (one silent, one a compile error, one a runtime crash) that come from picking wrong.
ObservableObject → @Observable: The Migration Guide That Skips the Marketing (and the Autoclosure Gotcha Apple Forgot to Mention)
Day 11 of the 30-day iOS series. Apple's migration guide makes ObservableObject → @Observable look like a find-and-replace. It mostly is — except for one quiet behavioral change: @StateObject only ran your initializer once, and @State runs it on every render. Here's the multiple-init bug that causes, why it's worst in exactly the init you were proud of, and how to fix it with a test that turns 'no side effects in init' into a hard, green invariant.