Error:XPC connection interrupted - iphone

I am scheduling notification by running the loop in an array.Notification is working fine.But my application is crashing with this error.I know that the OS stops working and os gets rebooted but if i dont call this scheduleNotification function then everything works fine so i know that the error is generation because of this function when i pops to other screen and comes back again my app gets crashg but i dont know why?? please help me out.
func scheduleNotification() {
if dictInfo.object(forKey: "name") !as AnyObject as ? String == "zzz" {
} else {
let calendar = Calendar.current
var calendarComponents = DateComponents()
let strDay = (dictInfo["dd"
as NSString] !as AnyObject).doubleValue
let strMonth = (dictInfo["mm"
as NSString]) !
let dayy = strDay
let monthh = strMonth
calendarComponents.hour = 11
calendarComponents.minute = 04
calendarComponents.day = Int(dayy!) - 2
print(calendarComponents.day)
let df = DateFormatter()
df.dateFormat = "MM" // if you need 3 letter month just use "LLL"
let datee1 = df.date(from: String(describing: monthh))
print(datee1)
let monthh11 = (Calendar.current as NSCalendar).component(.month, from: datee1!)
print(monthh11) // 5
//calendarComponents.year = Int(yearr!)
calendarComponents.month = Int(monthh11)
let newComponents = DateComponents(calendar: calendar, timeZone: .current, month: calendarComponents.month, day: calendarComponents.day, hour: calendarComponents.hour, minute: calendarComponents.minute)
if# available(iOS 10.0, * ) {
let strName: String = String(describing: dictInfo["name"] !)
let str2: String! = "Today is \(strName)\'s Birthday!"
let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: false)
let content = UNMutableNotificationContent()
content.title = "Alert Me!"
content.body = str2
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "myCategory"
content.userInfo = ((dictInfo as Any) as ? [AnyHashable: Any]) !
print(content.userInfo.count)
let request = UNNotificationRequest(identifier: strName, content: content, trigger: trigger)
// UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {
(error) in
if let error = error {
print("Uh oh! We had an error: \(error)")
} else {
}
}
}
}
MBProgressHUD.hide(
for: self.view, animated: true)
tableVieww.isHidden = false
//self.navigationItem.leftBarButtonItem?.isEnabled = true
}

Related

How to schedule local notification from iOS14 widget?

I would like to schedule a local notification from iOS14 widget.
How can I do it?
I tried implementing the following:
let center = UNUserNotificationCenter.current()
center.delegate = self
let content = UNMutableNotificationContent()
content.title = "Some Title"
content.body = "Some Body"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString,
content: content, trigger: trigger)
center.add(request) { (error) in
if error != nil {
// Handle any errors.
}
I did with this.
func createDate(day: Int, month : Int, hour: Int, minute: Int, year: Int)->Date{
var components = DateComponents()
components.hour = hour
components.minute = minute
components.year = year
components.day = day
components.month = month
components.timeZone = .current
let calendar = Calendar(identifier: .gregorian)
return calendar.date(from: components)!
}
// 📢///CreateNitification
func scheduleNotification(at date: Date, identifierUnic : String, body: String, titles:String) {
let triggerWeekly = Calendar.current.dateComponents([.day, .month, .hour,.minute, .year], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerWeekly, repeats: true)
let content = UNMutableNotificationContent()
content.title = titles
content.body = body
content.sound = UNNotificationSound.default
content.categoryIdentifier = "todoList2"
let request = UNNotificationRequest(identifier: identifierUnic, content: content, trigger: trigger)
// UNUserNotificationCenter.current().delegate = self
/// UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: ["textNotification2"])
/// UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print(" We had an error: \(error)")
}}
}
// Call
func callNotifications(){
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
let adte = createDate(day: 3, month: 6, hour: 16, minute: 51, year: 2021)
scheduleNotification(at: adte, identifierUnic: UUID().uuidString, body: "Widgets on Work", titles: "check 123")
}
func getTimeline(in context: Context, completion: #escaping (Timeline<Entry>) -> ()) {
callNotifications()
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
Notification is working fine
but one thing is pending, how can I call UNUserNotificationCenter.current().delegate = self?
Thanks

local notification with repeats

I am making a local notification that will run every year, the problem is that I need notifications that come based on the Hebrew calendar, that is, July 20, 2020 according to the Hebrew calendar 28 tamuz 5780 and if we add the year to 28 tamuz 5781 then according to the Gregorian calendar comes out on July 1, 2021, that is, according to the Gregorian calendar, the date changes, I also need to take into account the leap year, AnniversariesReminderService is responsible for the notification, thanks
July 20, 2020 is 28 tamuz 5780
but
28 tamuz 5781 is July 1, 2021
I need to automatically calculate this time difference so that every year I receive a notification according to the Jewish date
struct ReminderAnniversaries {
var id:Int!
var description:String!
var date:Date!
}
class AnniversariesReminderService {
fileprivate var formatter :DateFormatter {
let dateformatterDay = DateFormatter()
dateformatterDay.dateFormat = "yyyy.MM.dd HH:mm"
return dateformatterDay
}
func scheduleReminder(data: ReminderAnniversaries, complited: (() -> Void)? = nil) {
removeScheduledReminder(data: data)
let request = self.prepareNotificationRequest(data: data)
UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
if error != nil {
print("ERROR SCHEDULE NOTIFICATION TYPE: \(String(describing: "\(data.id!)")), ERROR: \(String(describing:error?.localizedDescription))")
}
complited?()
})
}
fileprivate func prepareNotificationRequest(data: ReminderAnniversaries) -> UNNotificationRequest {
let content = UNMutableNotificationContent()
content.sound = .default
content.title = "AppDisplayName".localized()
content.body = data.description
let fireDate = data.date!
var dateInfo = DateComponents()
let triggerDaily = Calendar(identifier: .hebrew).dateComponents([.year, .month, .day, .hour, .second], from: fireDate)
dateInfo.year = fireDate.year
dateInfo.month = fireDate.month
dateInfo.day = fireDate.day
dateInfo.hour = fireDate.hour
dateInfo.minute = fireDate.minute + 1
dateInfo.second = fireDate.second
content.userInfo = ["id": data.id, "date" : fireDate,
"description": data.description]
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
let requestIdentifier = "\(data.id!)"
let request = UNNotificationRequest(identifier: requestIdentifier,
content: content, trigger: trigger)
print("NOTIFICATION SCHEDULED: (String(describing: requestIdentifier))")
print("NOTIFICATION TITLE: \(String(describing: content.body))")
print("NOTIFICATION TIME: \(String(describing: self.formatter.string(from: fireDate)))")
return request
}
func removeScheduledReminder(data: ReminderAnniversaries) {
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["\(data.id!)"])
print("NOTIFICATION REMOVED: \(String(describing: "\(data.id!)"))")
}
func getScheduledReminderDate(data: ReminderAnniversaries) -> String? {
var scheduledDate: Date?
let semaphore = DispatchSemaphore(value: 0)
UNUserNotificationCenter.current().getPendingNotificationRequests { notifications in
notifications.forEach({ notification in
if let scheduledType = notification.content.userInfo["id"] as? Int, scheduledType == data.id {
scheduledDate = notification.content.userInfo["date"] as? Date ?? Date()
// continue;
semaphore.signal()
}
})
if scheduledDate == nil {
semaphore.signal()
}
}
semaphore.wait()
return scheduledDate != nil ? formatter.string(from: scheduledDate!) : nil
}
}
Setting of date
#objc func doneDatePicker(){
if isAlarmClock && stage != 1 {
datePicker.datePickerMode = .dateAndTime
pickerDone.setTitle("Done".localized(), for: .normal)
pickerCancel.setTitle("Back".localized(), for: .normal)
stage = 1
formatter.dateFormat = "dd-MMM-yyyy HH:mm"
} else if !isAlarmClock {
//1
formatter.dateFormat = "dd-MMM-yyyy"
formatter.calendar = Calendar(identifier: .gregorian)
let dateOfDied = formatter.string(from: datePicker.date)
selectedDate = datePicker.date
// result Jule 21 2020 г.
//2
formatter.calendar = Calendar(identifier: .hebrew) //convert to jewish date
formatter.dateFormat = "dd-MMM-yyyy"
jewishDatePicker.date = datePicker.date
jewishDatePicker.calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.hebrew)! as Calendar //convert to jewish calendar for adding year
//count of years between date of died and current date
let calendar = Calendar.current
// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: selectedDate)
let date2 = calendar.startOfDay(for: Date())
let components = calendar.dateComponents([.year], from: date1, to: date2)
var dayComponent = DateComponents()
dayComponent.year = components.year! + 1
let new_date = jewishDatePicker.calendar.date(byAdding: dayComponent, to: jewishDatePicker.date) // adding year by jewish calendar
jewishSelectedDate = new_date!
let hebDate = formatter.string(from: jewishSelectedDate)
jewishDatePicker.locale = Locale(identifier: "he")
jewishDatePicker.setDate(new_date!, animated: false)
print(jewishDatePicker.date)
// result Jule 9 2021 г.
//3
formatter.calendar = Calendar(identifier: .gregorian) //convert to gregorian date
let gregDate = formatter.string(from: new_date!)
// result Jule 09 2021 г.
alarmClock.isEnabled = true
alarmClockBtn()
var txt = Localized("You choosed", arguments: "\(dateOfDied)")
txt = txt + " " + "Jewish anniversary falls on".localized() + " " + "\(gregDate) (\(hebDate))," + " " + "select the date and time to remind you".localized()
text.text = txt
} else {
reminderTime = datePicker.date
pickerView.isHidden = true
}
}
#objc func addNotificationBtn(){
if !(name.text?.isEmpty ?? false) && !(parentName.text?.isEmpty ?? false) &&
jewishSelectedDate != nil && reminderTime != nil {
errorNotifier.notify("Done".localized(), title: "Notification configured".localized(), showOK: true) { [weak self] in
let remind = ReminderService()
var txt = Localized("You have set an anniversary reminder", arguments: self!.name.text!)
txt = txt + " " + "Бен(Бат)".localized() + " " + self!.parentName.text!
let data = ReminderAnniversaries(id: 11, description: txt, date: self?.reminderTime)
remind.anniversaries.scheduleReminder(data: data) {
print("ready")
}
self?.dismiss(animated: true, completion: nil)
}
} else if (name.text?.isEmpty ?? false) && (parentName.text?.isEmpty ?? false) {
errorNotifier.notify("Check the fields".localized(), title: "Fields must not be empty".localized(), showOK: true)
} else if jewishSelectedDate == nil {
errorNotifier.notify("Please select date if died".localized(), title:"", showOK: true)
} else if reminderTime == nil {
errorNotifier.notify("Please select a time for the anniversary reminder, the time is automatically set the day before the death anniversary".localized(), title: "Please select a time reminder".localized(), showOK: true)
}
}

Local Notification every X day - Swift

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
Lets say you want to trigger notification 2, 4 and 6 days from now, here is how you can do it:
For my example I added extension to Date
extension Date {
func adding(days: Int) -> Date? {
var dateComponents = DateComponents()
dateComponents.day = days
return NSCalendar.current.date(byAdding: dateComponents, to: self)
}
}
Then you could just create new notifications for dates specified, in this example 2, 4, 6 days from now
let date = Date()
for i in [2, 4, 6] {
if let date = date.adding(days: i) {
scheduleNotification(withDate: date)
}
}
func scheduleNotification(withDate date: Date) {
let notificationContent = UNMutableNotificationContent()
notificationContent.title = "Title"
notificationContent.subtitle = "Subtitle"
notificationContent.body = "Body"
let identifier = "Make up identifiers here"
let dateComponents = Calendar.autoupdatingCurrent.dateComponents([.day, .month, .year, .hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let notificationReques = UNNotificationRequest(identifier: identifier, content: notificationContent, trigger: trigger)
UNUserNotificationCenter.current().add(notificationReques) { error in
if let e = error {
print("Error \(e.localizedDescription)")
}
}
}
This should schedule 3 notifications - 2, 4, 6 days from now...
So thanks for the directions on here this is the final solution i came up with. Ensure you turn on background modes in app capabilities so the current week is updated. i did mine to every day.
Then the code with comments.
//: Playground - noun: a place where people can play
import UIKit
import UserNotifications
Lets create some helper clases to make it easier to work with dates
// HELPERS
extension Date {
public var weekday: Int {
return Calendar.current.component(.weekday, from: self)
}
public var hour: Int {
get {
return Calendar.current.component(.hour, from: self)
}
set {
let allowedRange = Calendar.current.range(of: .hour, in: .day, for: self)!
guard allowedRange.contains(newValue) else { return }
let currentHour = Calendar.current.component(.hour, from: self)
let hoursToAdd = newValue - currentHour
if let date = Calendar.current.date(byAdding: .hour, value: hoursToAdd, to: self) {
self = date
}
}
}
public var minute: Int {
get {
return Calendar.current.component(.minute, from: self)
}
set {
let allowedRange = Calendar.current.range(of: .minute, in: .hour, for: self)!
guard allowedRange.contains(newValue) else { return }
let currentMinutes = Calendar.current.component(.minute, from: self)
let minutesToAdd = newValue - currentMinutes
if let date = Calendar.current.date(byAdding: .minute, value: minutesToAdd, to: self) {
self = date
}
}
}
}
Then we create our custom notification struct
struct CustomNotification {
static func everyOtherDay(wtihStartDate startDate: Date) -> [Int]? {
//
let currentDate = Date()
// get initial week day from start date to compare dates
let weekDay = startDate.weekday
// Then we need to get week of years for both dates
let cal = Calendar.current
guard let weekA = cal.dateComponents([.weekOfYear], from: startDate).weekOfYear else { return nil}
guard let weekB = cal.dateComponents([.weekOfYear], from: currentDate).weekOfYear else {return nil}
// create two arrays for week days
let weekOne = [1,3,5,7]
let weekTwo = [2,4,6]
// then we create a module to check if we are in week one or week two
let currentWeek = (weekA - weekB) % 2
if currentWeek == 0 {
//week 1
return weekOne.contains(weekDay) ? weekOne : weekTwo
} else {
// week 2
return weekOne.contains(weekDay) ? weekTwo : weekOne
}
}
}
finally in our class where we create the notification. I personally use a notification manager. but to shwo you quickly
class AClass : NSObject {
func setupNotifications() {
let startDate = Date()
let weekDays = CustomNotification.everyOtherDay(wtihStartDate: startDate)
let cal = Calendar.current
let center = UNUserNotificationCenter.current()
if let weekDays = weekDays {
for day in weekDays {
let identifier = "Some Random ID"
let content = UNMutableNotificationContent()
content.title = "title"
content.body = "body"
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "SOME CATEGORY"
content.setValue("YES", forKeyPath: "shouldAlwaysAlertWhileAppIsForeground")
var components = cal.dateComponents([.hour, .minute], from:startDate)
components.weekday = day
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let request = UNNotificationRequest(identifier: identifier,
content: content, trigger: trigger)
center.add(request, withCompletionHandler: { (error) in
if let error = error {
// Something went wrong
print("ERROR ADDING NOTIFICATION TO CENTER \(error.localizedDescription)")
} else
{
print("ADDING NOTIFCIATION \(content.categoryIdentifier)")
}
})
}
}
}
}
Then we need to setup background fetch in our app and app delegate
// OVER IN APP DELEGATE
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// setup background refresh ensuring you turn it on in app capabilities
// trigger back ground refrsh once a day
UIApplication.shared.setMinimumBackgroundFetchInterval(86400)
return true
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// FETCH DATA and REFRESH NOTIFICATIONS
// We need to do this to ensure the current week value is updated to either 1 or 0
// You will need to delete all notifications with same same category first else your going to be getting both weeks notifications
let aClass = AClass()
aClass.setupNotifications()
}
Hope this helps somebody :D Thomas

Swift fixing array for notifications

I'm trying to fix my notifications displaying every day what should I pack up for school for next day.
Everything seems ok, but content.subtitle shows error :
Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1007dbb00)
Is there problem with array also? I searched for answer, but it looks like nobody used array for notification body. Is it even possible?
And if it's not can I replace it with better replacement?
Thanks for any help.
let plan = [
["dzien": "Sunday", "lekcje": nil],
["dzien": "Saturday", "lekcje":["pon1","pon2","pon3"]],
["dzien": "Tuesday", "lekcje":["wt1","wt2","wt3"]],
["dzien": "Wednesday", "lekcje":["sr1","sr2","sr3"]],
["dzien": "Thursday", "lekcje":["cz1","cz2","cz3"]],
["dzien": "Friday", "lekcje":["pt1","pt2","pt3"]],
["dzien": "Saturday", "lekcje": nil],
]
func getDayOfWeek() -> Int {
let myCalendar = Calendar(identifier: .gregorian)
let weekDay = myCalendar.component(.weekday, from: Date())
return weekDay - 1
}
#objc func registerLocal() {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
print("Sukces")
} else {
print("Nie dzieła")
}
}
}
#objc func scheduleLocal() {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
let d = getDayOfWeek()%6
let dzis = plan[d]
if dzis["lekcje"] != nil {
content.title = "Pack up"
content.subtitle = dzis["dzien"]
var lekcje = ""
for lekcja in dzis["lekcje"] {
lekcje+="\(lekcja)\n"
}
content.body = lekcje
content.userInfo = ["customData": "fizzbuzz"]
} else {
content.title = "Tommorow \(dzis["dzien"]), You don't have any subjects."
}
var dateComponents = DateComponents()
dateComponents.hour = 16
dateComponents.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
}
}
The problem is that the compiler infers the type of plans as [String:Any] and when you are trying to do content.subtitle = dzis["dzien"], dzis["dzien"] is of type Any and not String.
You have to cast it to String in order to work.
guard let subtitle = dzis["dzien"] as? String else {return}
content.subtitle = subtitle

UserNotification in 3 days then repeat every day/hour - iOS 10

UILocalNotification has been depreciated so I would like to update my code to the UserNotification framework:
let alertDays = 3.0
let alertSeconds = alertDays * 24.0 * 60.0 * 60.0
let localNotification:UILocalNotification = UILocalNotification()
localNotification.alertAction = "Reminder"
localNotification.alertTitle = "Reminder Title"
localNotification.alertBody = "Reminder Message"
localNotification.fireDate = Foundation.Date(timeIntervalSinceNow: alertSeconds)
localNotification.repeatInterval = .day
UIApplication.shared().scheduleLocalNotification(localNotification)
How can I set a similar daily or hourly repeat with the UserNotification framework after waiting for the initial notification?
let alertDays = 3.0
let alertSeconds = alertDays * 24.0 * 60.0 * 60.0
let content: UNMutableNotificationContent = UNMutableNotificationContent()
content.title = "Reminder Title"
content.subtitle = "Reminder Subtitle"
content.body = "Reminder Message"
let calendar = Calendar.current
let alarmTime = Foundation.Date(timeIntervalSinceNow: alertSeconds)
let alarmTimeComponents = calendar.components([.day, .hour, .minute], from: alarmTime)
let trigger = UNCalendarNotificationTrigger(dateMatching: alarmTimeComponents, repeats: true)
let request = UNNotificationRequest(identifier: workoutAlarmIdentifier,
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request)
{
(error) in // ...
}
It seems like this is not supported, but to make a workaround you could use:
let alertDays = 3.0
let daySeconds = 86400
let alertSeconds = alertDays * daySeconds
let content: UNMutableNotificationContent = UNMutableNotificationContent()
content.title = "Reminder Title"
content.subtitle = "Reminder Subtitle"
content.body = "Reminder Message"
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: (alertSeconds), repeats: false)
let request = UNNotificationRequest(identifier: workoutAlarmIdentifier,
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request)
{
(error) in // ...
}
in combination with didReceive(_:withContentHandler:) you can use:
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: (daySeconds), repeats: false)
I know this isn't optimal but it should work without using deprecated classes/methods. You use repeats: false since you are intercepting the notification just before the user receives it and creating a new notification. Additionally you can use it in combination with UNNotificationAction and UNNotificationCategory if you handle multiple notifications.
This should work:
func addNotificationForAlarm(alarm: MyAlarm) {
let myAlarmNotifContent = UNMutableNotificationContent()
myAlarmNotifContent.title = "Reminder"
myAlarmNotifContent.body = alarm.activity
myAlarmNotifContent.sound = UNNotificationSound.default()
if alarm.repeatDays.count == 1 {
} else {
for index in 1...alarm.repeatDays.count {
createNotif(date: alarm.date, weekDay: index, content: myAlarmNotifContent)
}
}
}
private func createNotif(date: Date, weekDay: Int, content: UNNotificationContent) {
var dateComponent = DateComponents()
dateComponent.weekday = weekDay
dateComponent.hour = Calendar.current.dateComponents([.hour], from: date).hashValue
dateComponent.minute = Calendar.current.dateComponents([.minute], from: date).hashValue
let myAlarmTrigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: true)
setupNotificationSettings()
let identifier = "Your-Notification"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: myAlarmTrigger)
let center = UNUserNotificationCenter.current()
center.add(request, withCompletionHandler: { (error) in
if error != nil {
//TODO: Handle the error
}
})
}