Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
246 views
in Technique[技术] by (71.8m points)

ios - Repeat interval for UNNotification

There is an option to set the repeat interval for UILocalNotification. Since Apple has deprecated UILocalNotification and recommend to use UNNotification instead, I couldn't find a way to set a notification with custom repeat interval with UNNotification.

    var comp = DateComponents()
    comp.year = 2019
    comp.month = 1
    comp.day = 9
    comp.hour = 14
    comp.minute = 14
    comp.second = 0
    let calendar = Calendar.current
    let notification: UILocalNotification = UILocalNotification()
    notification.category = "Daily Quote"
    notification.alertBody = "Body"
    notification.alertTitle = "Title"
    notification.fireDate = calendar.date(from: comp)
    notification.repeatInterval = NSCalendar.Unit.day
    UIApplication.shared.scheduleLocalNotification(notification)

So can I set a similar notification that repeats hourly or daily after waiting for the initial notification using the new UNNotification?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To mimic the UILocalNotification's API fireDate and repeatInterval you can create two triggers, one non-repeating which would be used for fireDate to kickoff and other repeating for repeatInterval.

Here's an example:

import UserNotifications

/// Schedules notificaiton to fire at specific date, and then it repeats by specified repeat component
/// (week, day, hour, etc.) and repeat interval. For example to repeat every 20minutes repeatComponent
/// would be .minute and repeatInterval would be 20.
/// - Parameters:
///   - fireDate: Date for initial notification delivery
///   - repeatComponent: Component by which repeating would be performed (week, day, hour, etc.)
///   - repeatInterval: Interval by which repeating by specified component would be performed. Defaults value is 1.
func scheduleNotification(fireDate: Date, repeatComponent: Calendar.Component, repeatInterval: Int = 1) {

    let content = UNMutableNotificationContent()
    content.title = "Daily Quote"
    content.body = "Inspirational quote."
    content.categoryIdentifier = "quote.category"

    UNUserNotificationCenter.current().requestAuthorization(
        options: [.alert,.sound])
    {
        (granted, error) in

        if let error = error {
            print("granted, but Error in notification permission:(error.localizedDescription)")
        }

        let fireTrigger = UNTimeIntervalNotificationTrigger(timeInterval: fireDate.timeIntervalSinceNow, repeats: false)

        let fireDateRequest = UNNotificationRequest(identifier: "quote.starter", content: content, trigger: fireTrigger)

        UNUserNotificationCenter.current().add(fireDateRequest) {(error) in
            if let error = error {
                print("Error adding firing notification: (error.localizedDescription)")
            } else {

                if let firstRepeatingDate = Calendar.current.date(byAdding: repeatComponent, value: repeatInterval, to: fireDate) {

                    let repeatingTrigger = UNTimeIntervalNotificationTrigger(timeInterval: firstRepeatingDate.timeIntervalSinceNow, repeats: true)

                    let repeatingRequest = UNNotificationRequest(identifier: "quote.repeater", content: content, trigger: repeatingTrigger)

                    UNUserNotificationCenter.current().add(repeatingRequest) { (error) in
                        if let error = error {
                            print("Error adding repeating notification: (error.localizedDescription)")
                        } else {
                            print("Successfully scheduled")
                            // Successfully scheduled
                        }
                    }

                }
            }
        }

        UNUserNotificationCenter.current().delegate = self
    }
}

Delegate (for debug):

extension ViewController: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        print("(notification.request.identifier): (Date())")
        UNUserNotificationCenter.current().getPendingNotificationRequests { (requests) in
            for request in requests {
                if let timeIntervalTrigger = request.trigger as? UNTimeIntervalNotificationTrigger {
                    print(Date(timeIntervalSinceNow: timeIntervalTrigger.timeInterval))
                }

            }
        }
    }
}

Usage for your requirement:

let interval = 7 // One week from now
if let fireDate = Calendar.current.date(byAdding: .day, value: interval, to: Date()) {
    _ = scheduleNotification(fireDate: fireDate, repeatComponent: .day)
}

NOTE

Specifying repeating interval less than 60sec would result with exception:

'NSInternalInconsistencyException', reason: 'time interval must be at least 60 if repeating'


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...