Detect If the Application in Background or Foreground in Swift

Detect if the application in background or foreground in swift

[UIApplication sharedApplication].applicationState will return current state of applications such as:

  • UIApplicationStateActive
  • UIApplicationStateInactive
  • UIApplicationStateBackground

or if you want to access via notification see UIApplicationDidBecomeActiveNotification

Swift 3+

let state = UIApplication.shared.applicationState
if state == .background || state == .inactive {
// background
} else if state == .active {
// foreground
}

switch UIApplication.shared.applicationState {
case .background, .inactive:
// background
case .active:
// foreground
default:
break
}

Objective C

UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (state == UIApplicationStateBackground || state == UIApplicationStateInactive) {
// background
} else if (state == UIApplicationStateActive) {
// foreground
}

How can I detect when the swift application is foreground from the background?

You probably need willEnterForegroundNotification.

Posted shortly before an app leaves the background state on its way to
becoming the active app.

Keep in mind thow that this notification posted olso after application(_:didFinishLaunchingWithOptions:) when opening the application for the first time.

When application opens for the first time the applicationState is inactive and when the application comes from the background the applicationState is background.

So, your code will be something like this:

token = NotificationCenter.default.addObserver(
forName: UIApplication.willEnterForegroundNotification,
object: nil,
queue: .main
) { (notification: Notification) in
if UIApplication.shared.applicationState == .background {
// Came from the background
}
}

How to detect when iOS app appears in foreground, with Swift?

You can use the applicationDidBecomeActive(_:) method of your UIApplicationDelegate. You should read up on the app lifecycle. Your app delegate would then need to inform your view controller in some fashion.

Or you can register your view controller as an observer of the UIApplicationDidBecomeActive notification. Documentation for that can be found here

How to detect if the main app is in the foreground in the NotificationServiceExtension?

From what I can tell, this isn't possible as of right now.

My guess is that Apple doesn't want these extensions to depend on the state of the main app.

What are proper places to detect foreground/background delegates in iOS?

Notification is one to many communication. If you really don't this functionality. you can use the protocol delegate method. you can assign a delegate, only when you need it.

and to solve your problem, you can move your observer to didSet of delegate variable. So, only when you assign a delegate, that time only observers will be added. if you don't set it, it will not be added for that viewController.

@objc protocol AppActivityTracker{
func appMovedToBackground()
func appMovedToForeground()
}
class BaseViewController: UIViewController {

var activityDelegate : AppActivityTracker? {
didSet{
//MARK:-Observer will be added only when you assign delegate.
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(activityDelegate?.appMovedToForeground), name: UIApplication.didBecomeActiveNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(activityDelegate?.appMovedToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
}

}

class MyViewController: BaseViewController {

override func viewDidLoad() {
super.viewDidLoad()
//MARK:- Assign delegate only when you need observers
activityDelegate = self
}
}
//MARK:- Assign delegate only when you need observers
extension MyViewController : AppActivityTracker{
func appMovedToBackground() {
print("Do whatever need to do for current view controllers on appMovedToBackground")
}

func appMovedToForeground() {
print("Do whatever need to do for current view controllers on appMovedToForeground")
}
}

Discussion from comment:-

Adding observer on viewWillAppear and removing observer on viewDidDisappear.

@objc protocol AppActivityTracker{
func appMovedToBackground()
func appMovedToForeground()
}
class BaseViewController: UIViewController {

var activityDelegate : AppActivityTracker? {
didSet{
if activityDelegate != nil{
addOberservers()
}
else{
removeOberservers()
}
}
}
func addOberservers(){
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(activityDelegate?.appMovedToForeground), name: UIApplication.didBecomeActiveNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(activityDelegate?.appMovedToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
func removeOberservers(){
let notificationCenter = NotificationCenter.default
notificationCenter.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
notificationCenter.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil)
}
}

class MyViewController: BaseViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//MARK:- Assign delegate only when you need observers
self.activityDelegate = self
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
//MARK:- Removing observer on view will disappear.
self.activityDelegate = nil
}
}
//MARK:- Assign delegate only when you need observers
extension MyViewController : AppActivityTracker{
func appMovedToBackground() {
print("Do whatever need to do for current view controllers on appMovedToBackground")
}

func appMovedToForeground() {
print("Do whatever need to do for current view controllers on appMovedToForeground")
}
}

Detecting application becoming going to the background and coming back to the foreground

The original code I wrote worked:

.onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification))

Added this as to the view:

struct ContentView: View {

var body: some View {
Text("Hello, world!")
.padding()
.onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) {
print("coming back!")
}
}

But I had the project being Multiplatform and it was creating some issues. I turned the project into a macOS only project and it worked.

Detect when a view controller goes to background and gets resumed

use UIApplicationDidBecomeActive for resume and UIApplicationWillResignActive for handle goes background

SwiftUI

Text("check application state!")
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) { _ in
print("User received on willResignActiveNotification!")
}
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
print("User received on didBecomeActiveNotification!")
}

Swift 5.x > above

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
}

override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.openAndCloseActivity), name: UIApplication.willResignActiveNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.openAndCloseActivity), name: UIApplication.didBecomeActiveNotification, object: nil)
}

@objc func openAndCloseActivity(_ notification: Notification) {
if notification.name == UIApplication.didBecomeActiveNotification{
// become active notifictaion
}else{
// willResignActiveNotification
}

}

Swift 5.x < below

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
}

override func viewDidLoad() {
super.viewDidLoad()

NotificationCenter.default.addObserver(self, selector: #selector(self.closeActivityController), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.openactivity), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)


}

and handle the method as

func closeActivityController()  {


}

func openactivity() {

//view should reload the data.
}

other notification types are

extension NSNotification.Name { 
@available(iOS 4.0, *)
public static let UIApplicationDidEnterBackground: NSNotification.Name

@available(iOS 4.0, *)
public static let UIApplicationWillEnterForeground: NSNotification.Name

public static let UIApplicationDidFinishLaunching: NSNotification.Name

public static let UIApplicationDidBecomeActive: NSNotification.Name

public static let UIApplicationWillResignActive: NSNotification.Name

public static let UIApplicationDidReceiveMemoryWarning: NSNotification.Name

public static let UIApplicationWillTerminate: NSNotification.Name

}


Related Topics



Leave a reply



Submit