iOS Local Notifications Testing - ios

In testing my local notifications, for some reason setting the date and time on my iOS device does not trigger my local notification to appear. My notification's fire date is set to be several days in the future. If I do wait a few days then I will see my local notification.
Why am I not seeing my local notification by setting the date and time on my device?
Below is a sample:
playNotification.FireDate = DateTime.Now.AddHours(71.67f);
playNotification.AlertAction = "Alert text";
playNotification.AlertBody = "Alert body";
playNotification.SoundName = UILocalNotification.DefaultSoundName;
playNotification.ApplicationIconBadgeNumber = badgeCount;
UIApplication.SharedApplication.ScheduleLocalNotification(playNotification);
I should mention that I changed 'AddHours' to 'AddSeconds' and tested this by waiting the specified number of seconds, and the notifications fired as expected. But somehow changing the date and time on my device does not.

You need to set the timeZone of the notifications. By default, the timeZone is set according to your location so it does not affect if you manually change your date and time. To achieve this, you need to set the timeZone to systemTimeZone().
Like this:
notification.timeZone = NSTimeZone.systemTimeZone()
I know this is in swift, but I know very little objective-c.
Hope this helps. :)

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.

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)

Update iOS icon badge number

I have a icon badge number update requirement. The app tracks tasks. I want the app to have a badge displaying the number of tasks due on each day. There are basically two cases when the badge number needs to be updated:
Midnight every day.
If new tasks are added or tasks are removed.
I know how to handle the second case. I can set badge number in the applicationResignActive func. However, the midnight automatic update is trick for me. To update the badge number, I need to call a func of the app to count the tasks that due on the day. However, in midnight, the app may be in all possible situations: foreground, background and not running. How can I do this? Thank you.
=====================================
To be clearer with my requirement, I would like the badge number to be updated everyday correctly, even the user never opens the app for a whole day or for consecutive several days. Also, I would try to avoid server side support because the app is a standalone app so far. Much appreciated for any help.
=====================================
Final update: I accepted Vitaliy's answer. However, his answer requires the app to be opened at least once every day. Otherwise, the event won't fire and the badge number cannot be updated.
Also, in my case, every time the app enters background event fires, I have to remove the existing notification and schedule a new one, with the up-to-dated badge number recalculated.
I am still interested in some way to handle the case that the app is not opened every day, how can you make sure the badge number is correct. So far, the easiest way is to setup some server and let it push notifications to the app regularly.
You can achieve it with UILocalNotification:
When app goes to background, calculate exact badge count number for nearest midnight
Schedule UILocalNotification at the nearest midnight with your calculated badge count
You will get notification at midnight, and app's badge count will be updated
Example code:
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Calculate nearest midnight or any other date, which you need
NSDate *nearestMidnight = [self nearestMidnight];
// Create and setup local notification
UILocalNotification *notification = [UILocalNotification new];
notification.alertTitle = #"Some title";
notification.alertBody = #"Some message";
notification.fireDate = nearestMidnight;
// Optional set repeat interval, if user didn't launch the app after nearest midnight
notification.repeatInterval = NSCalendarUnitDay;
// Calculate badge count and set it to notification
notification.applicationIconBadgeNumber = [self calculateBadgeCountForDate:nearestMidnight];
[application scheduleLocalNotification:notification];
}

Local Notification every 24 hours in Swift

I'm looking for a way to fire a local notification once every 24 hours from a certain time.
For example:
I have a date picker.
I set the date picker time to 3.02pm.
The next time it's 3.02pm fire a local notification.
Repeat this over and over.
I have managed to successfully call a local notification at a time chosen by a date picker but how do I go about repeating this every 24 hours?
You can repeat a local notification using the repeatInterval property.
To repeat a local notification every day, add this line to your code
myLocalNotification.repeatInterval = NSCalendarUnit.CalendarUnitDay
UILocalNotification is deprecated in iOS 10. Use UNNotificationRequest instead.
myNotificationRequest.trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60*60*24, repeats: false)
In Swift 3
myLocalNotification.repeatInterval = NSCalendar.Unit.day

iOS check if a UILocalNotification condition occurs

I read a lot of documentation and code about UILocalNotification. My alert occurs when the condition (a calculated value raise) a limit.
With localNotification.repeatInterval = NSHoursCalendarUnit
My Notification is resent every hours. How can I ask LocalNotificationCenter to make a calculation BEFORE sending (or not) the notification?
For exemple:
Value == 1 -> Notification, Value is one.
Every hours recalculate Value if Value changed -> Notification, value is changed
Thanks in advance for your help,
Jacques
Unfortunately you cannot set your own constraints when scheduling a local notification. The only thing you can do is to ignore the notification when it fires. (But when the application is closed you cannot do anything about it)

Resources