Why SwiftUI @State property can be initialized inside `init` this OTHER way:

There are a few ways to debug view lifetimes. You can add the "magic" line let _ = Self._printChanges() inside your view's body to see when and why it gets (re)evaluated. When the printed message says the identity changed, that's when any @State properties are captured to the view hierarchy and @StateObjects are lazy-initialised.

You can also get an idea of view identity by adding the wrapped property @Namespace var namespace to the view. Sometimes I prepend it to Self._printChanges() with any extra info about the view which helps me debug things like a view's title or URL or item ID, something like:

var body: some View {
  let _ = print(self.title, self.namespace, terminator: " -- ")
  let _ = Self._printChanges()
  ...
}

That little terminator helps keep the info on the same line.

When we talk about view lifetime, it's not the lifetime of the view struct but of a node in a view graph hidden inside SwiftUI's internals. AFAICT the @Namespace wrapped property refers to the ID of that node.

10 Likes