如何将可选包解包到变量中,然后在 while 循环的下一次迭代中使用该变量?



我在下面有一个名为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
}

最新更新