Why can't I cancel a repeating UILocalNotification? - ios

Ciao, tout le monde. In my Swift app, there is a UILocalNotification scheduled in a method that will be called after some time when the UIViewController is loaded, and it is repeating every hour (using repeatInterval = .CalendarUnitHour). I store this UILocalNotification instance in a private property in the UIViewController so that I can cancel it later on. When the user presses a button in the UIViewController, the action method will trigger the cancellation of the notification instance, by which I use this code (the code is also used in the deinit of the UIViewController:
if let notification = notificationProperty {
UIApplication.sharedApplication().cancelLocalNotification(notification)
notificationProperty = nil
}
I use a if-let statement here to prevent accidentally canceling a nil UILocalNotification. But even after it canceled the notification, the notification is still showing up every hour.
So why is it not cancelling properly? Thanks!

The notification that the system have is a copy of the one you are holding as a field. You can't cancel the one that you are holding since it is not a notification instance that is in the system.
You can cancel all the existing notifications by cancelAllLocalNotifications or find the one you want to cancel by iterating over all the existing instances by the scheduledLocalNotifications property.

Related

Any way to cancel a local notification from app delegate that is about to fire?

I'm in a situation where I need to cancel a local notification that is about to fire. I don't want to remove it but only cancel it for the current time. For context: I don't want to remove the notification because I have it set up to fire every day at a different hour, and it's just not convenient to delete & recreate given the app is notification heavy. Thank you.
Is masking the notification processing code a convenient solution?
So you will keep your notification setup while have the ability to enable/disable its effect by simply using a bool flag.

Swift UILocalNotification: Is it possible to fire an event when Notification is displayed?

So I know the didReceiveLocalNotification event is fired when a user selects an action on a Local Notification.
But, is an event fired prior to that when the notification is displayed as a banner or alert when the app is not active? And can that be accessed to do some background code?
I am looking for an answer in Swift if you can help.
No, local notifications do not and cannot awake the app when firing and the application is not active. The user must tap the notification, or perform a developer defined action on it before the app hears anything.
If you need your app to wake up, you need to use a remote notification with content available flag set.

Confusion about applicationDidBecomeActive and applicationWillEnterForeground

I have some confusion about the above two app delegation method: I read this link, and it shows that the applicationWillEnterForeground will gets called before applicationDIdBecomeActive gets called. I am not sure about the before means.
If I have a social app: in my applicationWillEnterForeground function, I will check if the there is a current user session; in my applicationDIdBecomeActive, I will reload the content on timelineViewController: Thus, if there is no current user session, the timeline cannot be shown. Suppose a user enter the app from background with no current user session, the applicationWillEnterForeground will show a login page to indicate that there is no user, however, will the next-get-called applicationDIdBecomeActive return back to timeline which are not supposed to show?
If I don't want to modify code in my other viewcontroller, or check user session in applicationDIdBecomeActive. Is there any code I can add in applicationWillEnterForeground function to prevent applicationDIdBecomeActive function running?
Another question: I notice that for some app like Facebook, if I press the home button, turning it to background, but immediately turn it back to screen, the app doesn't show a lot of changes; however, if I let it stay in background for like an hour, it will "freeze" for a while (looks like it is refreshing) when I turn it back to foreground. How does the delegation method design to realize that? Is the system decides which delegation method(the above two) to call basing on the time that the app stayed in background?
BTW, I am using swift as the main programming language of iOS
You can't prevent applicationDidBecomeActive from getting called.
You could set an instance variable in applicationWillEnterForeground which is read later to determine the flow your application uses.
To refresh or initiate VC your app after certain interval like Facebook you can do as follows:
In applicationDidEnterBackground
let app = UserDefaults.standard
let date = Date()
app.set(date, forKey: "activeDate")
In applicationWillEnterForeground
let user = UserDefaults.standard
var interval = 0
if let date = user.object(forKey: "activeDate") as? Date {
interval = Int(Date().timeIntervalSince(date)); print ( "AppDeligate: Inactive interval: \(interval)")
}
if interval > 7200 { // 2hr
// Initiate VC OR Refresh data here
}
if you check time interval in applicationDidBecomeActive, then app get initiate or refresh data when yo view notification from swiping down or swipe up for control center. so applicationWillEnterForeground is the best place to do so.

How to change view controller everyday at specific time in iOS

I have a case where a user needs to submit a form everyday before 8am.
When they submit, a confirmation view is overlaid to show the user they have submitted as well as stop them from submitting again.
After 8am, I want to clear the form and have the form view available again by hiding the overlaid view. I want to do this at one point in time at 8am if possible.
I was thinking about accomplishing this with NSTimer. Can I set a timer that will run at 8am that will clear the form and remove the overlay view?
Is there a better way to handle this scenario?
You could use a local push notification. Official doc here
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction.html
Something like that:
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate date]; // Replace me with your "event" date
localNotification.timeZone = [NSTimeZone localTimeZone];
localNotification.repeatInterval = kCFCalendarUnitDay;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
then you can "catch" the notification as the doc says
If your app is frontmost, the application:didReceiveRemoteNotification: or application:didReceiveLocalNotification:method is called on its app delegate If your app is not frontmost or not running you handle the notifications by checking the options dictionary passed to the application:didFinishLaunchingWithOptions: of your app delegate for either the UIApplicationLaunchOptionsLocalNotificationKey or UIApplicationLaunchOptionsRemoteNotificationKey key.
You can't use just a NSTimer, because it will not run when your app is closed, however another solution that involves NSTimer is to create a NSTimer for the event date, and then observe UIApplicationDidEnterBackgroundNotification, here if the timer is running, you'll stop the timer, persisting the timer.fireDate (you can save it in NSUserDefault for example), finally observing UIApplicationDidBecomeActiveNotification, you can recreate the timer (substracting the current time with the value that you saved previously) or just fire the action if the event time already passed on.
If you don't want to use a UILocalNotification you can dynamically define your initial view controller (VC) by:
Programmatically loading the VC in didFinishLoadingWithOptions: in AppDelegate
Or subclass your UINavigationController and set your rootController dynamically

Unable to Remove Local Notification from Lockscreen

In my app, at some point I need to display some notification to the user, in case user didn't respond to them, I need to remove that notification. Now, if I call cancelAllLocalNotifications function it does remove notification from notification center (also removes the alert from Home-screen, when the device is unlocked).
But when device is locked and notification is displayed on the lock-screen. After sometime, my app calls cancelAllLocalNotifications function. Now, this doesn't remove Notification from Lock-screen, however there is no item in notification center.
Using cancelAllLocalNotifications won't remove the already showed ones. It cancels all notifications that are scheduled. I don't think there is a way to clear a notification from the lock screen.
I dont know if it was not possible that time, but now you can cancel notification from the lockscreen. If anybody needs this now.
If you send a notification you have to store it somewhere to be able to identify it when it should be canceled.
All you have to do is
UIApplication.sharedApplication().cancelLocalNotification(notification)
to identify the notification which should be canceled you can set information in the userinfo property
notification.userInfo = ["title": item.title, "UUID": item.UUID]

Resources