我在下面有一个名为createNotifications()的方法,当警报的重复出现时,我尝试做一些花哨的事情daily
。我首先调用self.createNotificationForToday(),它运行良好,然后启动一个while循环并在每次迭代中调用self.createNotificationForTomorrow和ReturnNewDateComponents(),每次返回新的日期组件并将其用作下一次迭代的输入。这允许我每次和每次调用一个方法,迭代到"明天"并为当天创建通知。问题出在这一部分:
var newDateComponents = dateComponents
while numberOfCreatableNotifications > 0 {
guard var newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
return
}
numberOfCreatableNotifications = numberOfCreatableNotifications - 1
}
我正在尝试做的是每次通过 while 循环时重新初始化newDateComponents
变量并调用 createNotificationForTomorrowAnd...() 方法,并使用这些 newDateComponents 作为下次调用该方法的输入。我尝试这样做的方式有什么根本性的问题吗?有没有更好的方法?
创建通知():
private func createNotifications(dateComponents: DateComponents) {
if recurrence == .today {
createNotificationForToday(dateComponents: dateComponents)
} else if recurrence == .tomorrow {
let _ = createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: dateComponents)
} else if recurrence == .daily {
let center = UNUserNotificationCenter.current()
center.getPendingNotificationRequests { (notifications) in
var numberOfCreatableNotifications = 64 - notifications.count
self.createNotificationForToday(dateComponents: dateComponents)
var newDateComponents = dateComponents
while numberOfCreatableNotifications > 0 {
guard var newDateComponents =
self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
return
}
numberOfCreatableNotifications = numberOfCreatableNotifications - 1
}
}
} else {}
}
createNotificationForToday():
private func createNotificationForToday(dateComponents: DateComponents) {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Random Alarm"
content.subtitle = "It's time!"
content.body = self.note
content.sound = UNNotificationSound.default
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)
center.add(request) { (error) in
if error != nil {
print("error (String(describing: error))")
}
}
}
createNotificationForTomorrow和ReturnNewDateComponents():
private func createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: DateComponents) -> DateComponents? {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Random Alarm"
content.subtitle = "It's time!"
content.body = self.note
content.sound = UNNotificationSound.default
let calendar = Calendar.current
guard let date = calendar.date(from: dateComponents) else {
os_log("Could not unwrap date in createNotificationForTomorrow() in Alarm.swift", log: OSLog.default, type: .debug)
return nil
}
guard let tomorrow = calendar.date(byAdding: .day, value: 1, to: date) else {
os_log("Could not unwrap tomorrow in createNotificationForTomorrow() in Alarm.swift", log: OSLog.default, type: .debug)
return nil
}
let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)
let trigger = UNCalendarNotificationTrigger(dateMatching: newDateComponents, repeats: false)
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)
center.add(request) { (error) in
if error != nil {
print("error (String(describing: error))")
}
}
return newDateComponents
}
guard
语句创建的变量的作用域是包含guard
语句的块,该语句是while
循环的主体。
这意味着您使用guard
语句创建的newDateComponents
与您在while
外部创建的newDateComponents
不同,并且在每次迭代while
循环后,内部newDateComponents
将被丢弃。
你实际上不需要guard
语句;你可以将解包构建到你的while
:
var newDateComponents: DateComponents? = dateComponents
while numberOfCreatableNotifications > 0, let currentDateComponents = newDateComponents {
newDateComponents = self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: currentDateComponents)
numberOfCreatableNotifications -= 1
}
if numberOfCreateableNotifications > 0 {
os_log("Could not create all notifications
}
您可能可以重构它以提高效率并减少一个函数:
- 使用
Calendar
属性,这样就不需要继续实例化日历 - 有一个返回"明天"的功能
- 具有安排通知的功能
let calendar = Calendar.autoUpdatingCurrent
private func createNotifications(dateComponents: DateComponents) {
switch (recurrence) {
case .today:
createNotification(for: dateComponents)
case .tomorrow:
createNotification(for: day(after: dateComponents))
case .daily:
let center = UNUserNotificationCenter.current()
center.getPendingNotificationRequests { (notifications) in
var numberOfCreatableNotifications = 64 - notifications.count
var currentDay: DateComponents? = dateComponents
while numberOfCreatableNotifications > 0, current = currentDay {
createNotification(for: current)
currentDay = day(after: current)
numberOfCreateableNotification -= 1
}
if numberOfCreateableNotifications > 0 {
os_log("Could not create all notifications", type: .debug)
}
}
}
}
private func createNotification(for dateComponents: DateComponents) {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Random Alarm"
content.subtitle = "It's time!"
content.body = self.note
content.sound = UNNotificationSound.default
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)
center.add(request) { (error) in
if let err = error {
print("error (err.localizedDescription)")
}
}
}
private func day(after dateComponents: DateComponents) -> DateComponents? {
guard let date = calendar.date(from: dateComponents),
let tomorrow = calendar.date(byAdding: .day, value: 1, to: date)
else {
os_log("Could not calculate tomorrow in Alarm.swift", log: OSLog.default, type: .debug)
return nil
}
let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)
return newDateComponents
}
最后一点,当您需要实际计划通知时,传递Date
实例而不是DateComponent
实例并转换为DateComponent
一次可能会更好。
不能newDateComponents
从 警卫声明中的外部范围。您可以绑定到新变量并 然后将其分配给newDateComponents
:
var newDateComponents = dateComponents
while numberOfCreatableNotifications > 0 {
guard let nextDateComponents =
self.createNotificationForTomorrowAndReturnNewDateComponents(dateComponents: newDateComponents) else {
os_log("Could not unwrap newDateComponents in createNotifications() in Alarm.swift", log: OSLog.default, type: .debug)
return
}
newDateComponents = nextDateComponents
numberOfCreatableNotifications = numberOfCreatableNotifications - 1
}