How to Reset Local Notifications when App Re-opens - ios

I am developing a reminder app with custom Repeat Intervals for local notifications. What I basically want is the DueDate notification to fire then subsequent notifications fire afterwards.
So Notification1.fireDate = the DueDate.date
Notification2.fireDate = DueDate.date.dateByAdding(1000)
& continue for 10 or so times. Then when the app becomes active again, I want the line of notifications to loop again but start after the last notification, like a Queue.
This is all to create the illusion of custom repeat intervals. This is where I got the idea from, so it can be done https://stackoverflow.com/a/5765870/5601784

If you are not changing the fireDate, then there is no point in deleting the previously set notification and setting it again. However, to delete all the notification that your app has set you can do this.
UIApplication.shared.cancelAllLocalNotifications()
or
let app: UIApplication = UIApplication.shared
for event in app.scheduledLocalNotifications! {
let notification = event as UILocalNotification
app.cancelLocalNotification(notification)
}
print(app.scheduledLocalNotifications!.count))//prints -- 0
Then you can set the UILocalNotification with the new information.

Related

Creating multiple local notifications at once fails

I'm working with local notification on iOS, but I'm having some problems when iOS tries to create the notifications. Some of them are created and some won't.
After reviewing my code a lot, I found that it was failing at the point where it was creating the local notification.
UIApplication.sharedApplication().scheduleLocalNotification(notification)
The only reason I could think of was that creating the notifications inside a loop, around 50-60 notifications, was too much for iOS to process. I'm doing it this way because all the notifications have a different time and different day, and belong to different things.
This is my block to create the local notifications:
let createdUid = self.generateNotificationUUID()
// create a corresponding local notification
let notification = UILocalNotification()
/* Time and timezone settings */
notification.fireDate = self.buildTime()
notification.repeatInterval = NSCalendarUnit.WeekOfYear
notification.timeZone = NSTimeZone.systemTimeZone()
/* Information settings */
notification.alertBody = "Sector \(notificationData["sector"]!): located at \(notificationData["name"]!) closes in 15 min."
notification.alertAction = "Open"
/* Badge settings */
notification.applicationIconBadgeNumber = UIApplication.sharedApplication().applicationIconBadgeNumber + 1
notification.soundName = "ring.caf"
notification.userInfo = ["UUID": createdUid, ]
/* Schedule the notification */
UIApplication.sharedApplication().scheduleLocalNotification(notification)
And all this code is inside a loop. The same loop before calling the notification creation, dynamically builds the notificationData array.
The notification data array contains the sector, the name, and the time and day.
Time and day is used to calculate the notification fire date.
Sector and Name are used for the alert body.
And all the four values are used to generate the UID (UUID).
If I put a print and remove the UIApplication.sharedApplication()... all the data looks good and what it needs to be.
I've tried, to solve the problem, using
dispatch_async(dispatch_get_main_queue()) {...}
and
dispatch_sync(dispatch_get_main_queue()) {...}
But with async I received the same result that I had without it, and using sync my screen freezes.
I kind of lost with this, I'm sure that my issues are because iOS doesn't process in time all the notification creation, but I dunno how to fix it.
I hope someone can help me, I'm using XCode 7.3.1 and Swift 2.2
From the documentation: https://developer.apple.com/library/ios/documentation/iPhone/Reference/UILocalNotification_Class/
An app can have only a limited number of scheduled notifications; the
system keeps the soonest-firing 64 notifications (with automatically
rescheduled notifications counting as a single notification) and
discards the rest.

Local Notification for Alarm Snooze

I am working on an alarm application and I am using local notification for that. Now I want to add snooze functionality to my alarm and alert show minimum distance 1 minute.
I am set Multiple alarm in my application so how can I managed it's?
UILocalNotification instances have a userInfo property of type NSDictionary. This can be used for storing information that you can later use for identifying what the notification was for.
For example, you could add the following code before firing the notification:
notification.userInfo = #{kAlarmIdentifier: alarm.identifier"};
where kAlarmIdentifier is a constant string used as a key. Then, when the notification is triggered, you can get the alarm that caused it with something like:
MYAlarm *alarm = [alarmManager getAlarmForIdentifier:notification.userInfo[kAlarmIdentifier]];

iOS UILocalNotification scheduled, but not fired

I'm making an application where I want local notifications. And something strange is happening. I schedule the notification:
static func setNotification(body: String, departure: Double, notification_info: Dictionary<String, String> )
{
let notification = UILocalNotification()
notification.alertBody = body
notification.fireDate = NSDate(timeIntervalSinceNow: departure)
notification.alertAction = "ShowDetails"
notification.userInfo = notification_info
notification.soundName = UILocalNotificationDefaultSoundName
UIApplication.sharedApplication().scheduleLocalNotification(notification)
print("notification over: " + String(departure))
print("-------" + String( notification.fireDate ))
}
I print in how much seconds i am supposed to get an notification.
I go to background mode, and keep watching when I will get an notification. when the time has passed, I get no notification, even though I am sure I am in background mode. (within Xcode I look at the debug navigator > Energy Impact, and it is saying I am in background).
When I restart my phone, and run the application, it does show the notification. Everything works perfect. And then later, after some more testing and using the application, my notifications stop working again (even though the notifications are still scheduled. I am following all the scheduled notifications with:
UIApplication.sharedApplication().scheduledLocalNotifications
I am still new with Swift, and I have no idea why this is happening. It's making me crazy not knowing why my notification is not firing, even though it is scheduled and everything...
Could anyone help me? If you need more information, please ask.
Edit:
I did set the permissions
The notifications are set in the AppDelegate
The departure time definitely is right
I made a mistake by not adding an unique ID to the notification (notification.userInfo was not always unique), and overwrites the previous scheduled notification. Thats why it something does work and sometimes doesn't.
Fixed the problem by making it unique.
Thanks
Since iOS 8.0, You have to ask for permission for local notifications as remote notifications:
let notificationSettings = UIUserNotificationSettings(forTypes: UIUserNotificationType.Alert, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(notificationSettings)
See more details in Location Notifications

Setting Reminders/Alarms in iOS8-iOS9

Main question: Should I be using local notifications, alarms, or reminders if I want attach due dates to tasks in my app? I want them to get a notification even if the app isn't running when the deadline arrives.
I found this tutorial on using UILocalNotification which it says can:
gives us the ability to cast notifications to a user without running the application
However, it was written six years ago and also states that this was introduced in iOS4. I know that a lot changes over 5 iOS versions.
I also read, alternatively, that I could use Event Kit. However, that seems more complicated than UILocalNotification.
Lastly, I could use probably take the current date/time and reminder date/time and create a timer to countdown.
So if I just want to attach due dates to tasks in my app (they don't need to show up in reminders or in the calendar), what's the best method and why?
I found following chunk of code here. This is also a good tutorial for how to create event in application.
var notification = UILocalNotification()
notification.alertBody = "Todo Item \"\(item.title)\" Is Overdue" // text that will be displayed in the notification
notification.alertAction = "open" // text that is displayed after "slide to..." on the lock screen - defaults to "slide to view"
notification.fireDate = item.deadline // todo item due date (when notification will be fired)
notification.soundName = UILocalNotificationDefaultSoundName // play default sound
notification.userInfo = ["UUID": item.UUID, ] // assign a unique identifier to the notification so that we can retrieve it later
notification.category = "TODO_CATEGORY"
UIApplication.sharedApplication().scheduleLocalNotification(notification)

Good pattern for UILocalNotifications and applicationIconBadgeNumber

My app schedules UILocalNotifications to be delivered to its users at varying times of the user's choice.
I'm running into a situation with how to manage the applicationIconBadgeNumber in this scenario.
As we know, you have to set the badge number at the time you create the notification. My problem is that the state of the number of badges can change at any time. Consider this scenario:
1) User gets 3 notifications.
2) User creates a new notification to alert her at a given point of time in the future. This notification carries the value of 1 plus the current value of the application badge (3).
3) User goes about their business. In the process of their business, they clear all 3 notifications (and, thus, badge numbers) they currently have by viewing them or otherwise using the app.
4) After the given amount of time passes, the notification appears in iOS, along with its previously calculated value (4, if you don't remember).
5) The application badge is now, 4 even though the user only has one actual notification.
I have searched up and down, but I cannot find an answer to this question which almost certainly has a simple answer I'm completely missing. How do I solve this quandary?
Since your app cannot look in the future, and know which events you'll handle immediately, and which ones you'll leave 'pending' for a while, there's some trick to do :
When notifications are handled by your app (by tapping on the notification(s), icon, ...), you have to :
get a copy of all pending notifications
'renumber' the badge number of these pending notifications
delete all pending notifications
re-register the copy of the notifications with their corrected badge
numbers again
Also, when your app registers a new notification, it has to check how many notifications are pending first, and register the new notification with with :
badgeNbr = nbrOfPendingNotifications + 1;
Looking at my code, it will get clearer. I tested this, and it's definitely working :
In your 'registerLocalNotification' method you should do this :
NSUInteger nextBadgeNumber = [[[UIApplication sharedApplication] scheduledLocalNotifications] count] + 1;
localNotification.applicationIconBadgeNumber = nextBadgeNumber;
When you handle the notification (appDelegate), you should call the method below, which clears the badge on the icon and renumbers the badges for pending notifications (if there are any)
Note that the next code works fine for 'sequential' registered events. If you would 'add' events in between pending ones, you'll have to 're-sort' these events first. I didn't go that far, but I think it's possible.
- (void)renumberBadgesOfPendingNotifications
{
// clear the badge on the icon
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
// first get a copy of all pending notifications (unfortunately you cannot 'modify' a pending notification)
NSArray *pendingNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications];
// if there are any pending notifications -> adjust their badge number
if (pendingNotifications.count != 0)
{
// clear all pending notifications
[[UIApplication sharedApplication] cancelAllLocalNotifications];
// the for loop will 'restore' the pending notifications, but with corrected badge numbers
// note : a more advanced method could 'sort' the notifications first !!!
NSUInteger badgeNbr = 1;
for (UILocalNotification *notification in pendingNotifications)
{
// modify the badgeNumber
notification.applicationIconBadgeNumber = badgeNbr++;
// schedule 'again'
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
}
}
Credits to #Whassaahh

Resources