Before I begin please don't burn me as I know this has been asked hundreds of times on here with no reliable answer but I believe there's a solution using background refresh. https://medisafe.com/ app seems to have solved it!
The goal : To trigger a local notification at a specified time every x days
My solution
step 1: get timer interval from start date and odd occurrence (this case 2) days from (edited)
step 2: set interval timer on this difference with a repeat
step 3: activate background refresh ( if the app is even terminated it will load the app in the background and give me a small window to perform some tasks)
step 4. set background refresh to trigger once a day
step 5: perform get items api which will refresh all timers and notifications
step 6 sit back and smile with amazement at my solution
but this fails.
so a timer interval
let newTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 172800,repeats: true)
but this will just reset the timer every day when the background fetch is performed and it will trigger 2 days from NOW and not from the start date.
So there must be a way of comparing dates hours and minutes (start date, x date, and current date to work out the timer interval value.
currently im using calendar components. to trigger everyday im doing the following
var triggerType : DateComponents? {
var triggerT : DateComponents?
var cal = Calendar(identifier: .gregorian)
cal.firstWeekday = 2
if let notificationModel = self.notificationModel {
switch notificationModel.reminderType {
case .daily?, .weekly?:
if let date = notificationModel.date {
triggerT = cal.dateComponents([.weekday, .hour, .minute], from:date)
if let weekday = notificationModel.weekday {
triggerT?.weekday = weekday
}
}
case .alternateDays?:
if let date = notificationModel.date {
triggerT = cal.dateComponents([ .hour, .minute], from:date)
// THIS IS WHERE I NEED HELP
}
case .monthly?:
if let date = notificationModel.date {
triggerT = cal.dateComponents([.day,.hour,.minute], from: date)
}
case .yearly?:
triggerT = Calendar.current.dateComponents([.month,.day,.hour,.minute], from: (notificationModel.date)!)
case .oneOff?:
triggerT = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute], from: (notificationModel.date)!)
case .none:
DispatchQueue.main.async {
if let category = self.notificationModel?.category, let title = self.notificationModel?.title {
Toast.down("An error was discovered in \(category). Please change the occurance value for the following \(title)")
}
}
}
} else {
print("NOTIFICATION MODEL IS CORRUPT")
}
return triggerT
}
func add(notification: NotificationModel){
let content = UNMutableNotificationContent()
if let title = notification.title,
let body = notification.body,
let identifier = notification.identifier {
content.title = title
content.body = body
content.sound = UNNotificationSound.default()
content.categoryIdentifier = (notification.category?.rawValue)!
content.setValue("YES", forKeyPath: "shouldAlwaysAlertWhileAppIsForeground")
var trigger : UNCalendarNotificationTrigger?
if let triggerType = self.triggerType {
if let occurance = notification.occurance {
if occurance > 0 {
}
}
trigger = UNCalendarNotificationTrigger(dateMatching: triggerType, repeats: true)
} else {
return
}
let interval = Date().timeIntervalSince1970
let identifierString = "2\(interval)"
var request : UNNotificationRequest!
if notification.reminderType == .alternateDays {
print("ADDING TIMER NOTIFICATION")
print("REMINDER TIME = \(notification.date)")
// 172800 = two days
let newTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 172800,
repeats: true)
request = UNNotificationRequest(identifier: identifierString,
content: content, trigger: newTrigger)
} else {
request = UNNotificationRequest(identifier: identifierString,
content: content, trigger: trigger)
}
center.add(request, withCompletionHandler: { (error) in
if let error = error {
// Something went wrong
print(error.localizedDescription)
} else
{
print("ADDING NOTIDCIATION \(content.title)")
}
})
//SNOOZE OR DELETE NOTIFICATIONS
let snoozeAction = UNNotificationAction(identifier: "Snooze", title: "Snooze", options: [])
let deleteAction = UNNotificationAction(identifier: "UYLDeleteAction",title: "Delete", options: [.destructive])
//Create a category with the actions: This requires another unique identifier (you probably want to define these magic strings in an enum):
let category = UNNotificationCategory(identifier: notification.category!.rawValue,
actions: [snoozeAction,deleteAction],
intentIdentifiers: [], options: [])
//Register the category with the notification center. It is recommended to do this early in the app lifecycle.
center.setNotificationCategories([category])
//To include this action in our notifications we need to set the category in the notification content:
} else {
print("Failed to add notification")
}
}
however, I want every other day and dont want to use the 64 notification limit.
thanks for your time
Thomas
