migrating from UILocalNotification to UNUserNotification swift
migrating from UILocalNotification to UNUserNotification swift
I'm migrating to NUUserNotification but I'm having problems as I'm learning notifications with the newer framework and I don't know the older. I hope this is not some duplicate as I read a lot of posts and tutorial to how to migrate but haven't found something that made me understand how to apply to this case. The code I'm updating is not mine and took me time understanding it. It's a clone of the iOS Alarm ( https://github.com/natsu1211/Alarm-ios-swift) that I incorporate in my app to perform things at scheduled time/days etc etc... The two things I'm having trouble to understand are the notification repetitions, as far as I understood is now for every week day or a single time right? The fireDate parameter is depreciated so how would I rewrite this? :
private func minFireDateWithIndex(notifications: [UILocalNotification]) -> (Date, Int)?
if notifications.isEmpty
return nil
var minIndex = -1
var minDate: Date = notifications.first!.fireDate!
for n in notifications
let index = n.userInfo!["index"] as! Int
if(n.fireDate! <= minDate)
minDate = n.fireDate!
minIndex = index
return (minDate, minIndex)
The other code I'm having trouble updating is the checking for existing notifications that now getPendingNotificationRequestsWithCompletionHandler:]. It's if let n = UIApplication.shared.scheduledLocalNotificationsinside the old function that define the notification, that I think I have updated for the remaining part.
Old code:
getPendingNotificationRequestsWithCompletionHandler:]
if let n = UIApplication.shared.scheduledLocalNotifications
func setupNotificationSettings() -> UIUserNotificationSettings
var snoozeEnabled: Bool = false
if let n = UIApplication.shared.scheduledLocalNotifications
if let result = minFireDateWithIndex(notifications: n)
let i = result.1
snoozeEnabled = alarmModel.alarms[i].snoozeEnabled
// Specify the notification types.
let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.sound]
// Specify the notification actions.
let stopAction = UIMutableUserNotificationAction()
stopAction.identifier = Id.stopIdentifier
stopAction.title = "OK"
stopAction.activationMode = UIUserNotificationActivationMode.background // choose activation mode for app on tapping notification
stopAction.isDestructive = false
stopAction.isAuthenticationRequired = false
let snoozeAction = UIMutableUserNotificationAction()
snoozeAction.identifier = Id.snoozeIdentifier
snoozeAction.title = "Snooze"
snoozeAction.activationMode = UIUserNotificationActivationMode.background
snoozeAction.isDestructive = false
snoozeAction.isAuthenticationRequired = false
let actionsArray = snoozeEnabled ? [UIUserNotificationAction](arrayLiteral: snoozeAction, stopAction) : [UIUserNotificationAction](arrayLiteral: stopAction)
let actionsArrayMinimal = snoozeEnabled ? [UIUserNotificationAction](arrayLiteral: snoozeAction, stopAction) : [UIUserNotificationAction](arrayLiteral: stopAction)
// Specify the category related to the above actions.
let alarmCategory = UIMutableUserNotificationCategory()
alarmCategory.identifier = "myAlarmCategory"
alarmCategory.setActions(actionsArray, for: .default)
alarmCategory.setActions(actionsArrayMinimal, for: .minimal)
let categoriesForSettings = Set(arrayLiteral: alarmCategory)
// Register the notification settings.
let newNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: categoriesForSettings)
UIApplication.shared.registerUserNotificationSettings(newNotificationSettings)
return newNotificationSettings
New code edit:
func setRouteNotification(_ date: Date, onWeekdaysForNotify weekdays:[Int], snoozeEnabled:Bool, onSnooze: Bool, soundName: String, routeName: String, index: Int)
// Notification content
let routeCheckNotificationContent = UNMutableNotificationContent()
let datesForNotification = correctDate(date, onWeekdaysForNotify: weekdays)
routeCheckNotificationContent.title = "Hello!! Are you ready to cycle?"
routeCheckNotificationContent.body = "Check route for alerts?"
routeCheckNotificationContent.categoryIdentifier = Id.notificationCategory
routeCheckNotificationContent.sound = UNNotificationSound.init(named: soundName + ".mp3") // check for the + ".mp3"
// Define actions
let check = UNNotificationAction(identifier: Id.checkActionIdentifier, title: " Check", options: [.foreground])
let wait = UNNotificationAction(identifier: Id.waitActionIdentifier, title: "Wait", options: )
// Define category
let routeCategory = UNNotificationCategory(identifier: Id.notificationCategory, actions: [check, wait], intentIdentifiers: , options: )
// Register category
UNUserNotificationCenter.current().setNotificationCategories([routeCategory])
let repeating: Bool = !weekdays.isEmpty
routeCheckNotificationContent.userInfo = ["snooze" : snoozeEnabled, "index": index, "soundName": soundName, "routeName": routeName, "repeating" : repeating]
//repeat weekly if repeat weekdays are selected
//no repeat with snooze notification
if !weekdays.isEmpty && !onSnooze
syncAlarmModel()
for d in datesForNotification
if onSnooze
alarmModel.alarms[index].date = Scheduler.correctSecondComponent(date: alarmModel.alarms[index].date)
else
alarmModel.alarms[index].date = d
// Notification trigger
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents(in: .current, from: d)
let newComponents = DateComponents(calendar: calendar, timeZone: .current, month: components.month, day: components.day, hour: components.hour, minute: components.minute, second: components.second, weekday: components.weekday)
let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: true)
// Notification Request
let routeNotificationRequest = UNNotificationRequest(identifier: "routeNotificationRequest", content: routeCheckNotificationContent, trigger: trigger)
// Add request
UNUserNotificationCenter.current().add(routeNotificationRequest) (Error) in
if Error != nil
print("something went wrong with adding notification")
var weekdays: [Int]!is an array populated in WeekdaysViewController ( a TableViewController ), selecting the rows.
var weekdays: [Int]!
Now when I select any day, notification won't fire.
2 Answers
2
If I understand correctly, you want to have a repeated local notification.
If so, you only need to setup your notification with
let dateInfo = Calendar.current.dateComponents([.weekday,.hour,.minute], from: aDateWithTheDayHourAndMinuteYouWantToTriggerTheNotification)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: true)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
Et voila
weekday: components.weekday
You’re welcome, happy to help
– Mikael
Sep 12 '18 at 2:22
After modification when I select any day from the WeekdaysViewController notification just won't fire, any ideas?
– vincenzo
Sep 14 '18 at 19:12
I have a strange behaviour. The notification seem not to fire the day you set it bue it dors next day.. weird right? Yesterday i did set a notification for 00:01 fiday and saturday .. it fired . This morning i set one for 7:33 saturday included..it did'nt fire..
– vincenzo
Sep 15 '18 at 5:46
Can you have a look at my edits? I have this strange behaviour that i really don't understand. Having added the parameter .weekday for repetition does automatically set repetitions to every day? Could be my weekday array conflicting with that?
– vincenzo
Sep 15 '18 at 8:46
@Mikael. @Honey. After struggling a bit with code, because I thought that I could only use .weekday component to set repetitions I found that I could use the same logic of setting up a notification per day of repetition using Date as I store the selected dates into an array, so I did set a for in loop to set a new notification with unique identifier for each stored date.
Final code is:
func setRouteNotification(_ date: Date, onWeekdaysForNotify weekdays:[Int], snoozeEnabled:Bool, onSnooze: Bool, soundName: String, routeName: String, index: Int)
// Notification content
let routeCheckNotificationContent = UNMutableNotificationContent()
let datesForNotification = correctDate(date, onWeekdaysForNotify: weekdays)
routeCheckNotificationContent.title = "Hello!! Are you ready to cycle?"
routeCheckNotificationContent.body = "Check route for alerts?"
routeCheckNotificationContent.categoryIdentifier = Id.notificationCategory
routeCheckNotificationContent.sound = UNNotificationSound.init(named: soundName + ".mp3") // check for the + ".mp3"
// Define actions
let check = UNNotificationAction(identifier: Id.checkActionIdentifier, title: " Check", options: [.foreground])
let wait = UNNotificationAction(identifier: Id.waitActionIdentifier, title: "Wait", options: )
// Define category
let routeCategory = UNNotificationCategory(identifier: Id.notificationCategory, actions: [check, wait], intentIdentifiers: , options: )
// Register category
UNUserNotificationCenter.current().setNotificationCategories([routeCategory])
let repeating: Bool = !weekdays.isEmpty
routeCheckNotificationContent.userInfo = ["snooze" : snoozeEnabled, "index": index, "soundName": soundName, "routeName": routeName, "repeating" : repeating]
//repeat weekly if repeat weekdays are selected
//no repeat with snooze notification
if !weekdays.isEmpty && !onSnooze
syncAlarmModel()
var counter = 0
for d in datesForNotification
if onSnooze
alarmModel.alarms[index].date = Scheduler.correctSecondComponent(date: alarmModel.alarms[index].date)
else
alarmModel.alarms[index].date = d
// Notification trigger
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents(in: .current, from: d)
var newComponents = DateComponents(calendar: calendar, timeZone: .current, month: components.month, day: components.day, hour: components.hour, minute: components.minute, second: components.second, weekday: components.weekday)
newComponents.weekday = weekdays[counter]
let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: true)
// Notification Request
// let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let routeNotificationRequest = UNNotificationRequest(identifier: "routeNotificationRequest(counter)", content: routeCheckNotificationContent, trigger: trigger)
// Add request
UNUserNotificationCenter.current().add(routeNotificationRequest) (Error) in
if Error != nil
print("something went wrong with adding notification")
print("added request(counter)")
counter = ( counter + 1 )
print(alarmModel.alarms)
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I so just added
weekday: components.weekdayto my own ``newComponents`and it should be it. I do get notification and actions. Great. I just have to try and se if repetitions on chosen days will work. I'll do a test and by tonight I'll get back with result. Thank you.– vincenzo
Sep 10 '18 at 15:01