iosswiftuilocalnotificationnsusernotification

Swift: Converting Local Notification to User Notification IOS 10


I have recently updated my project to IOS 10, which has caused any local notifications I had registered to not fire. I have tried to convert the local notification to user notifications but it is not having the same effect. Here is the original code I tried to convert. Within viewDidLoad:

        guard let settings = UIApplication.shared.currentUserNotificationSettings else { return
        }
        if settings.types == UIUserNotificationType() {
            let ac = UIAlertController(title: "Cant Schedule", message: "No Permission", preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            present(ac, animated: true, completion: nil)
            return
        }


        var dateComp: DateComponents = DateComponents()
        dateComp.year = 2017;
        dateComp.month = 01;
        dateComp.day = 28;
        dateComp.hour = 11;
        dateComp.minute = 0;
        (dateComp as NSDateComponents).timeZone = TimeZone.current

        let calender:Calendar = Calendar(identifier: Calendar.Identifier.gregorian)
        let date:Date = calender.date(from: dateComp)!


        let notification = UILocalNotification()
        notification.fireDate = date
        notification.alertBody = "Notification!"
        notification.alertAction = "You just Received a notification!"
        notification.soundName = UILocalNotificationDefaultSoundName
        notification.userInfo = ["customField1": "w00t"]
        notification.repeatInterval = NSCalendar.Unit.weekOfYear
        UIApplication.shared.scheduleLocalNotification(notification)

This caused a local notification to fire at 11:00 am every saturday.

Here is the code I used to try and achieve the same effect in IOS 10:

func scheduleNotification(at date: Date) {
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents(in: .current, from: date)
let newComponents = DateComponents(calendar: calendar, timeZone: .current, month: components.month, day: components.day, hour: components.hour, minute: components.minute)

let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: true)

let content = UNMutableNotificationContent()
content.title = "Notification"
content.body = "You just Received a notification!"
content.sound = UNNotificationSound.default()

let request = UNNotificationRequest(identifier: "textNotification", content: content, trigger: trigger)


UNUserNotificationCenter.current().add(request) {(error) in
    if let error = error {
        print("Error")
    }
}
}

In viewDidLoad:

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) {(accepted, error) in
    if !accepted {
        print("Error")
    }
}

This code works fine if the user selects the date using a datePicker, but I can't figure out how to programmatically set the date of the notification to the same date I had in the local notification (2017-28-01 11:00), and also how to make the notification fire every week at the same time as there is no repeatInterval property.


Solution

  • Could you explain how you could only specify for example Monday at 11:00 am

    It's just a matter of leaving out everything that doesn't apply to the repeated value. Thus, in your case you want to specify the date components hour:11 and weekday:2 and nothing else.

    To understand how this works, run this in a playground:

    let dc = DateComponents(hour:11, weekday:2)
    let greg = Calendar(identifier: .gregorian)
    let d = greg.nextDate(after: Date(), matching: dc, matchingPolicy:.nextTime)
    

    You will see that d is this coming Monday at 11AM.

    That is exactly what UNNotificationTrigger will do to figure out when to send this notification.

    Now, if you also set this to be a repeats trigger, you have just specified every Monday at 11AM.