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