Detect App Moving to Background in SwiftUI
Reading time: 1 min
This recipe shows two ways of detecting when your app goes to foreground or background.
NotificationCenter solution
The first solution works on iOS 13+ and any device, iPhone or iPad, and is generally the one you should use. First, add these two extensions to your app:
extension View {
func onAppCameToForeground(perform action: @escaping () -> Void) -> some View {
self.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
action()
}
}
func onAppWentToBackground(perform action: @escaping () -> Void) -> some View {
self.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) { _ in
action()
}
}
}
Then, you can use it on any View
you'd like:
var body: some View {
VStack {
Text("Some content")
}
.onAppCameToForeground {
print("App came to foreground")
}
.onAppWentToBackground {
print("App went to background")
}
}
ScenePhase solution
The second solution relies on observing the scenePhase
environment variable, which changes its value as the app state changes. The thing is, this only works only on iOS 14+, and only on iPhone: since an iPhone app only has a single screen, a change in the scenePhase
equals a change in the entire app, which isn't true for iPad apps.
@Environment(\.scenePhase) var scenePhase
var body: some View {
VStack {
Text("Some content")
}
.onChange(of: scenePhase) { newPhase in
switch newPhase {
case .background:
print("App went to background")
case .active:
print("App became active (or came to foreground)")
case .inactive:
print("App became inactive")
@unknown default:
print("Well, something certainly happened...")
}
}
}
Tip: You can track app (in)activity via the NotificationCenter
solution by subscribing to didBecomeActiveNotification
and willResignActiveNotification
, respectively.