iOS NSNotificationCenter to check whether the app came from background to foreground
Have you tried UIApplicationWillEnterForegroundNotification
?
The app also posts a UIApplicationWillEnterForegroundNotification notification shortly before calling applicationWillEnterForeground:
to give interested objects a chance to respond to the transition.
Subscribe to notification:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(yourUpdateMethodGoesHere:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
Implement a code, that need to be called:
- (void) yourUpdateMethodGoesHere:(NSNotification *) note {
// code
}
Don't forget to unsubscribe:
[[NSNotificationCenter defaultCenter] removeObserver:self];
What's the best way to detect when the app is entering the background for my view?
You can have any class interested in when the app goes into the background receive notifications. This is a good alternative to coupling these classes with the AppDelegate.
When initializing said classes:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
Responding to the notifications
-(void)appWillResignActive:(NSNotification*)note
{
}
-(void)appWillTerminate:(NSNotification*)note
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil];
}
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
}
NSNotificationCenter callback while app in background
The solution to the second part of the question was to raise the scope of the object containing the callback code. I raised it to the level of the containing ViewController. This seems to work. I still can't figure out how to raise the Notification (i.e. execute the call back) if the notification comes while the app is in the background/suspended. This prevented the object containing the callback from being cleaned up.
swift - How to detect from what ViewController application enter background?
On AppDelegate Methods: applicationDidEnterBackground
or applicationWillEnterForeground
, you can get the top most UIViewController. It is well explained on this question: Get top most UIViewController
How to determine whether the app is opened from NotificationCenter (Local Notification) or the app icon when app is killed
How can I know if the app is opened by pressing the notification and not the app icon
As you said, implement the UNUserNotificationCenterDelegate method didReceive
. If the user tapped your notification, it will be called, launching your app if it isn’t running.
Triggering a specific action when the app enters foreground from a local notification in iOS? (using swift)
If I want a view controller to be notified when the app is brought back to the foreground, I might just register for the UIApplication.willEnterForegroundNotification
notification (bypassing the app delegate method entirely):
class ViewController: UIViewController {
private var observer: NSObjectProtocol?
override func viewDidLoad() {
super.viewDidLoad()
observer = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { [unowned self] notification in
// do whatever you want when the app is brought back to the foreground
}
}
deinit {
if let observer = observer {
NotificationCenter.default.removeObserver(observer)
}
}
}
Note, in the completion closure, I include [unowned self]
to avoid strong reference cycle that prevents the view controller from being deallocated if you happen to reference self
inside the block (which you presumably will need to do if you're going to be updating a class variable or do practically anything interesting).
Also note that I remove the observer even though a casual reading of the removeObserver
documentation might lead one to conclude is unnecessary:
If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its dealloc method.
But, when using this block-based rendition, you really do need to remove the notification center observer. As the documentation for addObserver(forName:object:queue:using:)
says:
To unregister observations, you pass the object returned by this method to
removeObserver(_:)
. You must invokeremoveObserver(_:)
orremoveObserver(_:name:object:)
before any object specified byaddObserver(forName:object:queue:using:)
is deallocated.
Related Topics
Is Iboutletcollection Guaranteed to Be of Correct Order
Check If My iOS Application Is Updated
How to Create a PDF File Programmatically in an iOS Application
How to Use Afnetworking or Sthttprequest to Make a Request of a Soap Web Service
How Long Does a Push Notification Sit in Queue Before Being Removed
Uibarbuttonitem Custom View in Uinavigationbar
Nearby Bluetooth Devices Using Swift 3.0
Why Does Unexpected Non-Void Return Value in Void Function Happen
Why Must a Protocol Operator Be Implemented as a Global Function
Application Identifier Entitlement Value Has Changed
Setting Up a Plist to Store Application Data (Not Settings) for an iPhone Game
Sending Latitude and Longitude to Server When App Is in Background
Uibutton with Single Press and Long Press Events Swift
Load a .Tmx (Tiled Map) in Sprite Kit
Error: Uitableview Jump to Top with Uitableviewautomaticdimension
How to Connect Iboutlet from Storyboard to Uiview Subclass
How to Change Pagetabview Programmatically in iOS 14, Swiftui 2