Application state and push notification - swift

I have a server that successfully generates push notifications and sends them to devices. On the app side, if the user is already in the app or if the user enters the app from the notification I can easily 'find' the notification and run the necessary code to action the notification (app delegate gets invoked and the notification is stored in NSUserDefaults which I can then access throughout the app).
However, if the user has the app running in the background (for example, user was in the app, but then switched to another app), when the user reopens the app from the app icon, the app simply returns to the last state it was in and no code actually gets invoked (which is kind of what you expect).
What I am trying to figure out is how to either invoke AppDelegate again so that I can extract the notification before I return to the current state or how do I invoke some code so that I can intercept the notification.
Thoughts?

If I understood your question correctly, you want to be notified when coming out of background state. How the appdelegate method
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

Here is my solution.
On 'App Resume', In AppDelegate, I check the badge and store push if badge value is greater than 0:
func applicationDidBecomeActive(application: UIApplication) {
let installation = PFInstallation.currentInstallation()
if installation.badge != 0 {
NSUserDefaults.standardUserDefaults().setObject(true, forKey: "push")
NSNotificationCenter.defaultCenter().postNotificationName("indicatePush", object: nil)
installation.badge = 0
installation.saveEventually()
}}
The call to NSNotificationCenter, invokes a registered method in my base class, where I set the push variable to true
In the sub-class, on viewDidLoad I register two methods (you might only need one of them):
NSNotificationCenter.defaultCenter().addObserver(self, selector: "appplicationIsActive:", name: UIApplicationDidBecomeActiveNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "applicationEnteredForeground:", name: UIApplicationWillEnterForegroundNotification, object: nil)
Add the call to the 'pull from server' to one of the two methods. In my case:
func appplicationIsActive (notification: NSNotification){
refresh()
}
You're done!

Related

Detect application minimize event for UIKIt for Mac?

When i minimize the application applicationDidEnterInBackground not called for Mac Catalyst. After some search i found that Background delegate methods not called for Mac Catalyst but foreground method of Scene delegate called.
is there any way to track or handle minimize delegate methods like NSWindowDelegate have?
Thanks
Well, if you check NSWindowDelegate.windowWillMiniaturize: you'll notice that its parameter is just a notification (its name is NSWindowWillMiniaturizeNotification).
So, you can simply observe that notification to get notified whenever a window in your app is about to be minimized:
NotificationCenter.default.addObserver(forName: NSWindow.willMiniaturizeNotification, object: nil, queue: nil) { notification in
print("This window is about to be minimized:", notification.object)
}
You can also do the same to get notified about other events like:
NSWindow.didMiniaturizeNotification: After the window is minimized.
NSWindow.didDeminiaturizeNotification: After the window is restored/deminimized.
NSWindow.willEnterFullScreenNotification: Before entering full screen.
NSWindow.didEnterFullScreenNotification: After entering full screen.
NSWindow.willExitFullScreenNotification: Before exiting full screen.
NSWindow.didExitFullScreenNotification: After exiting full screen.
Full list of notifications here.

how to refetch data that has already been fetched

My tableView uses prefetching to cache images and works perfectly when I start the app but once I close out of the app, sending it to the background (not fully shutting it down) and click the app again, the cached images are gone but because the tableView already prefetched these images prior to closing, the prefetch method is not being called on the indexPaths that were previously loaded.
Im looking for a method or logic I can code that would call the prefetching method again based off the current indexPath allowing the indexPaths that were previously loaded and then lost to be reloaded. any help would be great?
When your app enters from background to foreground, in appDelegate file inside method
func applicationDidBecomeActive(_ application: UIApplication) {
NotificationCenter.default.post(Notification.init(name: Notification.Name(rawValue: "appDidEnterForeground")))
}
Now you can set up listeners in your UIViewControllers setup code :
override func viewDidLoad() {
NotificationCenter.default.addObserver(self,
selector: #selector(self.YOUR_METHOD_NAME),
name: NSNotification.Name(rawValue: "appDidEnterForeground"),
object: nil)
}
inside your UIViewController create your custom method and check if thats get called implement your logic inside that method.
#objc func YOUR_METHOD_NAME() {
print("notification method called")
}

Local notification pull into background function triggering

when I terminate my app into twice tap on home button then how can I call my function in background service on swift 4.
because I work on local push notification , after API calling then getting data and that's data put into notification.
I am not entirely sure this is what you mean, but if you want to call a function/do something right before your app enters the background(what happens when someone double clicks the home button) you can use the default applicationWillResignActive(_:) or applicationDidEnterBackground(_:) function in the AppDelegate class. See the apple docs for more information about app states and functions.
If you want to execute code when the app terminates, use applicationWillTerminate(_:).
So in AppDelegate.swift(I deliberately left the original Xcode default comment in for clarification):
class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
yourGoToBackgroundFunction()
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
yourSaveDataFunction()
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
yourSaveDataFunction()
}
}

Notifications from NotificationCenter while debugging

How can I ensure, that an observer within a NotificationCenter is called only once - especially when the app crashes/has to be stopped by Xcode?
Let's assume I want to print the notification NSNotification.WhatHaveYou.
init() {
NotificationCenter.default.addObserver(forName: NSNotification.Name.WhatHaveYou, object: nil, queue: OperationQueue.main, using: { (notification) in
print(notification)
})
}
Which works fine.
Apple stated in its documentation for NotificationCenter.default.addObserver(forName:, object:, queue:, using:):
The block to be executed when the notification is received.
The block is copied by the notification center and (the copy) held
until the observer registration is removed.
But how can I make this observer registration is removed, so that for the next app start there is no further notification registered?
Especially when the app crashes or I stop the application via Xcode, the observer is not removed, so the notification will show up multiple times - to be more precise: lastNumberOfOccurences = lastNumberOfOccurences +1
How to handle that properly?
Update
So far I find these resources
http://benscheirman.com/2012/01/careful-with-block-based-notification-handlers/
http://sealedabstract.com/code/nsnotificationcenter-with-blocks-considered-harmful/
Observers that are subscribed to NotificationCenter cannot survive app restarts. This is because the objects that you've added get removed from memory as soon as the app dies, be it a crash or a normal termination. This said, all observers need to be added during runtime of your app and they can be also removed during your app's runtime. As soon as the app terminates, all associated memory gets freed, including subscribed observers.

Method in swift which will be executed after user open app from background

does exist some function/method which is executed when user open app from background (not new fresh launch, just from sleep on the background)? Thanks
this doesnt work for me as i expect:
override func viewWillAppear(animated: Bool) { ...
This isn't specific to swift.
Your app delegate will get sent a applicationWillEnterForeground message. The signature in Swift looks like this:
optional func applicationWillEnterForeground(_ application: UIApplication)
Next, the system will broadcast a UIApplicationWillEnterForegroundNotification. You can set up a notification listener in any class to listen for that notification.