Limiting local notifications set at the same to one - ios

I've implemented a date picker for setting reminders which sends a local notification. During testing, I noticed I can set a reminder multiple times at the same time. I assumed the system would recognize I've already set it once at that particular time, and would not save another reminder. Surprisingly, the app sent more than once notification at the same time.
I figured I implemented this incorrectly so I decided to test the default Clock app. Again, I set two alarms at the same time, and I got two notifications concurrently:
Is this a normal behaviour for notifications? Are my assumptions wrong? Maybe this would've been okay when the user wanted to assign different messages to separate notifications. However, in my case, the app is supposed to remind users for one simple task, with a static message.
Is there a way to fix this "problem"? The way I see it, if I've already set a reminder, the app should still show that a new reminder has been saved, but not actually save the new one.

This is the normal and intended behaviour. Two notifications might have the same time but completely different data, so they are not restricted to one per unit time.
I would set the unique identifier of the notification and keep track of them in an array.
Here is an example:
let center = UNUserNotificationCenter.current()
// Setup content
let content = UNMutableNotificationContent()
content.title = "Notificaion title"
content.body = "Yoir text here"
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "YouCanHaveDifferentCategories"
content.userInfo = ["myKey": "myValue"]
// Setup trigger time
var calendar = Calendar.current
let now = Date()
let date = calendar.date(byAdding: .second, value: 10, to: now)
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: false)
// Create request
// Set any unique ID here. I use the UUID tools. This value is used by notificaion center, but I alsp store it in an array property of the relevant object in my data model, so the notification can be removed if the user deletes that object.
let uniqueID = UUID().uuidString
let request = UNNotificationRequest(identifier: uniqueID, content: content, trigger: trigger)
// Add the notification request
center.add(request)
You can then selectively delete notifications with these methods, as long as you have a record in an array or your data model of the identifiers. You can pass an array to delete multiple at once.
center.removePendingNotificationRequests(withIdentifiers: "UniqueID")
center.removeDeliveredNotifications(withIdentifiers: "UniqueID")

Related

Running local notifications with hourly interval every day for specific amount of time

How can I make my app to be able to fire local notifications every day with customisable interval but only for allocated amount of time, for example: from 10:00 to 20:00pm?
Now I only implemented repeated notifications with custom interval:
func beginNotifications(_ config: UserConfig) {
let interval = config.notificationInterval
let center = UNUserNotificationCenter.current()
center.removeAllPendingNotificationRequests()
let content = UNMutableNotificationContent()
content.title = "Content title"
content.subtitle = "Content body"
content.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: interval, repeats: true)
let request = UNNotificationRequest(identifier: "notification", content: content, trigger: trigger)
center.add(request)
}
By far I only came up with solution - to make two separate methods using Timer, which will start and stop notification function daily, and enable Background Mode for the app.
The first solution came to my mind if scheduling the local push notification N-times (how many times as you want). You just need to make the identifier unique of course.
By far I only came up with solution - to make two separate methods
using Timer, which will start and stop notification function daily,
and enable Background Mode for the app.
This isn't recommended imo, and if you push this, you might need to deal with Apple review team.

Question on how to proceed with UNUserNotificationCenter 64 limit

I am trying to make a reminder app and all my notification repeat is set to true
Example :
var dateComponents = DateComponents()
dateComponents.weekday = 1
dateComponents.hour = Int(hour)
dateComponents.minute = Int(minute)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let requestIdentifier = "\(timeArrayToSaveInMobile[indexTime].alarmId!)Sunday"
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
I've browse around here and some people mentioned that the system keeps the soonest-firing 64 notifications.
So, if I have already reached the limit but I set another notification that will fire earlier than some of the notification in the (64 list) it should replace one of the notification right? Since it will fire earlier that some of the pre-set notification in the list.
My problem is similar to this ios 10 swift 3 add more than 64 local notifications does not keep soonest
Notifications will reset when you open the app, thus you can set/send another 64 after every time you close the application.
The system discards scheduled notifications in excess of this limit, keeping only the 64 notifications that will fire the soonest. Recurring notifications are treated as a single notification.
in your example you have set one notification for Sunday which is only count one for each Sunday.

Swift - Daily Local Notification with Event

In my application users will set a time. On that time I need to send them a daily notification with the count of newly created appointments. For example assume there are 3 appointments having on "01-03-2017". So on that day, at a selected time user should get a notification mentioning that "you have 3 new appointments". Newly added appointments will be saved in local realm db.
Actually what I have to do is every day user mentioned time, there should be run a code segment and check whether are there any new appointments in db. If so need to fire local notification. Even app is close this should work. I saw that in Android we can do this using alarm manager. But in swift I didn't found a way to do this.
I am not a expert in swift. So appreciate if you can give me a solution with a explanation. Thank you for your time.
You will not be able to run code at desired time, as iOS prevents from doing this.
Though, if the realm database is updated, it means the app is running at some point to add the new appointments.
When it occurs, you could have a function similar to the following to create a local notification
func createLocalNotification(atDate date: DateComponents, appointmentCount: Int) {
var content = UNMutableNotificationContent()
content.title "You have \(appointmentCount) appointment(s) today"
content.badge: appointmentCount
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: false)
let notificationRequest = UNNotificationRequest(identifier: "notification-request-\(date.day!)-\(date.month!)-\(date.year!)", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(notificationRequest)
}

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)

Resources