In SwiftUI, I want to use onChange(of:, action:) function for scenePhase, but the build fails.
struct MyView: View {
    @Environment(\.scenePhase) var scenePhase
    @State private var timerStatus: TimerStatus
    var body: some View {
        VStack {
            Text(...)
            Button(...)
        }
        .onChange(of: scenePhase) { oldState, newState in // Error on this line
            if newState == .active {
                // some code
            } else if oldState == .active {
                // some code
            }
        }
        .onChange(of: timerStatus) { oldState, newState in
            // some code
        }
    }
}
enum TimerStatus {
    case paused
    case runningActive
    case runningInactive
}
I get the following error:
"Contextual closure type '(ScenePhase) -> Void' expects 1 argument, but 2 were used in closure body"
Do you have any idea why I get this error, and how to fix it?
I'm developing the program for iOS 18.2 in Xcode.
When I used "Jump to Definition" function for the onChange() function, the older version of onChange was shown:
@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
extension View {
    @inlinable nonisolated public func onChange<V>(of value: V, perform action: @escaping (_ newValue: V) -> Void) -> some View where V : Equatable
}
onChange(of: timerStatus) works without the error and "Jump to Definition" shows the newer definition:
@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *)
extension View {
    nonisolated public func onChange<V>(of value: V, initial: Bool = false, _ action: @escaping (_ oldValue: V, _ newValue: V) -> Void) -> some View where V : Equatable
}
    
                
In SwiftUI, I want to use onChange(of:, action:) function for scenePhase, but the build fails.
struct MyView: View {
    @Environment(\.scenePhase) var scenePhase
    @State private var timerStatus: TimerStatus
    var body: some View {
        VStack {
            Text(...)
            Button(...)
        }
        .onChange(of: scenePhase) { oldState, newState in // Error on this line
            if newState == .active {
                // some code
            } else if oldState == .active {
                // some code
            }
        }
        .onChange(of: timerStatus) { oldState, newState in
            // some code
        }
    }
}
enum TimerStatus {
    case paused
    case runningActive
    case runningInactive
}
I get the following error:
"Contextual closure type '(ScenePhase) -> Void' expects 1 argument, but 2 were used in closure body"
Do you have any idea why I get this error, and how to fix it?
I'm developing the program for iOS 18.2 in Xcode.
When I used "Jump to Definition" function for the onChange() function, the older version of onChange was shown:
@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
extension View {
    @inlinable nonisolated public func onChange<V>(of value: V, perform action: @escaping (_ newValue: V) -> Void) -> some View where V : Equatable
}
onChange(of: timerStatus) works without the error and "Jump to Definition" shows the newer definition:
@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *)
extension View {
    nonisolated public func onChange<V>(of value: V, initial: Bool = false, _ action: @escaping (_ oldValue: V, _ newValue: V) -> Void) -> some View where V : Equatable
}
    
        
            
                
                    
                    The scenePhase environment value in SwiftUI reflects only the current lifecycle state of the app. It does not provide the oldValue in the onChange(of:) method.
Store the previous value in a separate variable:
@Environment(\.scenePhase) var scenePhase
@State private var previousScenePhase: ScenePhase?
var body: some View {
    VStack {
        Text("...")
        Button("...")
    }
    .onChange(of: scenePhase) { newState in
        if let oldState = previousScenePhase {
            if newState == .active {
                // Handle activation
            } else if oldState == .active {
                // Handle deactivation
            }
        }
        previousScenePhase = newState
    }
}

@State private var timerStatus: TimerStatus = .paused, that is give it an initial value. – workingdog support Ukraine Commented Jan 6 at 7:26