一个本地通知是否可以有两个 DateComponents?

Is it possible to have two DateCompontents for one Local Notification?

我正在尝试为本地通知设置两个不同的时间 - 默认时间是每天上午 10 点(如果用户不触摸日期选择器来选择他们自己的通知时间,也就是零),一个基于根据用户的输入。用户输入一个确实有效,每天都会发送通知,但如果没有选择时间,则默认时间无效。

这是我的代码,有人能告诉我我做错了什么吗?我基本上想检查如果用户输入为 NIL,它应该恢复为默认时间设置。

在设置中:

IBOutlet var userDatePicker: UIDatePicker!

IBAction func pickerValueChanged(_ sender: UIDatePicker) {
    var selectedTime = Date()
    selectedTime = sender.date

    // convert to data type DateComponents
    let convertedSelectedTime = calendar.dateComponents([.hour, .minute,], from: selectedTime)
    let delegate = UIApplication.shared.delegate as? AppDelegate
    delegate?.sendNotification(with: convertedSelectedTime)
    UserDefaults.standard.set(selectedTime, forKey: "SavedTime")
}

在 AppDelegate 中:

func sendNotification(with userSelectedTime: DateComponents?) {
    let center = UNUserNotificationCenter.current()
    let content = UNMutableNotificationContent()
    content.title = "Testing"
    content.body = "testing"
    var defaultTime = DateComponents()
    defaultTime.hour = 10
    defaultTime.minute = 00`// trying to set default time to 10 am if user never picks a time`
    let components = userSelectedTime ?? defaultTime//option between the two
    let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
    let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
    center.add(request)
}

试试这个。它的所有字段都是可选的。所以你可以使用你需要的那些。

DateComponents(calendar:timeZone:era:year:month:day:hour:minute:second:nanosecond:weekday:weekdayOrdinal:quarter:weekOfMonth:weekOfYear:yearForWeekOfYear:)

let triggerDaily = DateComponents(calendar: Calendar.current,
  timeZone: Calendar.current.timeZone,
  hour: 10, // Use 22 if PM 
  minute: 00,
  second: 00,
  nanosecond: 00)

let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: false)

更多信息

DateComponents - Apple


更新

pickerValueChanged 中,您会在每次 DatePicker 值更改时安排通知。那很不好。在那里你应该只存储日期。

func pickerValueChanged(_ sender: UIDatePicker) {
    UserDefaults.standard.set(sender.date, forKey: "SavedTime")
}

sendNotification 应该只发送通知。

func sendNotification(with dateComponents: DateComponents) {
    let center = UNUserNotificationCenter.current()
    let content = UNMutableNotificationContent()
    content.title = "Testing"
    content.body = "testing"
    let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
    let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
    center.add(request)
}

UIApplication 有一个 life 方法,当 App 进入后台时调用。您可以在那里安排通知。

func applicationDidEnterBackground(_ application: UIApplication) {
    let date = UserDefaults.standard.value(forKey: "SavedTime") as? Date
    if let date = date {
        let convertedSelectedTime = Calendar.current.dateComponents([.hour, .minute,], from: date)
        sendNotification(with: convertedSelectedTime)
    } else {
        let dateComponent = DateComponents(calendar: Calendar.current,
          timeZone: Calendar.current.timeZone,
          hour: 10, // Use 22 if PM
          minute: 00,
          second: 00,
          nanosecond: 00)
       sendNotification(with: dateComponent)
    }
}

如果 UserDefaaults 中存在,则使用 SavedTime。否则使用 10:00.


如果您使用 SceneDelegate,请使用 sceneDidEnterBackground 而不是 applicationDidEnterBackground

func sceneDidEnterBackground(_ scene: UIScene) {

}

它们都是生命周期方法。

更多信息。

Managing Your App's Life Cycle

UIApplication