Contents

onChange(of:perform:)

Adds an action to perform when the given value changes.

Declaration

nonisolated func onChange<V>(of value: V, perform action: @escaping (V) -> Void) -> some Scene where V : Equatable

Parameters

  • value:

    The value to check when determining whether to run the closure. The value must conform to the Equatable protocol.

  • action:

    A closure to run when the value changes. The closure provides a single newValue parameter that indicates the changed value.

Return Value

A scene that triggers an action in response to a change.

Discussion

Use this modifier to trigger a side effect when a value changes, like the value associated with an Environment value or a Binding. For example, you can clear a cache when you notice that a scene moves to the background:

struct MyScene: Scene {
    @Environment(\.scenePhase) private var scenePhase
    @StateObject private var cache = DataCache()

    var body: some Scene {
        WindowGroup {
            MyRootView()
        }
        .onChange(of: scenePhase) { newScenePhase in
            if newScenePhase == .background {
                cache.empty()
            }
        }
    }
}

The system may call the action closure on the main actor, so avoid long-running tasks in the closure. If you need to perform such tasks, detach an asynchronous background task:

.onChange(of: scenePhase) { newScenePhase in
    if newScenePhase == .background {
        Task.detached(priority: .background) {
            // ...
        }
    }
}

The system passes the new value into the closure. If you need the old value, capture it in the closure.