@Observable vs ObservableObject

SwiftUI Mid-level Swift 5.9+ iOS 17+ Reviewed By Alok Singh

Predict the output

profile.name changes. Which view bodies re-run?

@Observable final class Profile {
    var name = "Ana"
    var avatarURL: URL?
}
struct NameView: View {
    let profile: Profile
    var body: some View { Text(profile.name) }
}
struct AvatarView: View {
    let profile: Profile
    var body: some View { AsyncImage(url: profile.avatarURL) }
}
Options
Hint 1 of 1

Which body reads name?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: B Only NameView

Correct. Only NameView's body read name.

Why not the others?
  • A Both NameView and AvatarView. That is ObservableObject behaviour. Observation tracks per property.
  • C Neither, because let properties aren't observed. Observation tracks reads in body regardless of wrappers.
  • D Every view in the app. Only views that read the changed property update.

30-second answer

@Observable is a macro that tracks which properties each view's body actually reads, and updates only those views when one of them changes. ObservableObject publishes one objectWillChange for any @Published change, so every observing view updates. Observation also needs no wrappers for reading: a plain property is enough.

Practise saying it · 45 s. No recording, just a timer

Explain how Observation decides which views update.

Say your answer out loud, then check which of these points you covered:

  • Tracks property reads in body
  • Only affected views update
  • Macro on classes only
  • Migration from ObservableObject

Deep dive

Tracking happens per property access during body, including through arrays and nested models.

Use @ObservationIgnored for properties that shouldn't trigger updates.

@Observable only works on classes.

withObservationTracking gives the same tracking outside SwiftUI; Observations (Swift 6.2) streams changes as an AsyncSequence.

Common mistakes

  • Wrapping @Observable models in @StateObject or @ObservedObject.
  • Adding @Published inside an @Observable class.
  • Assuming a plain let model isn't observed.

Senior take & follow-ups

Seniors explain the performance win (fewer re-renders) and the migration steps, not just the syntax.

Follow-up questions

Think of your answer first, then open the hint.

  1. How do you migrate gradually?

    Show hint

    Convert one model at a time; switch @StateObject to @State and drop @Published.

  2. What about iOS 16 support?

    Show hint

    Keep ObservableObject or use a back-port; @Observable needs iOS 17.

Suggest a fix if something here is wrong or out of date.