我正在开发一个药物提醒应用程序,用户可以在其中添加每日,每周或隔日的药物提醒,并选择提醒时间。这是一个简单的实现每天和每周,但我很难找到一个解决方案,为交替的日子,因为苹果不提供任何选项,通过频率值与日历通知触发。我在网上找遍了,但没有找到任何解决办法。到目前为止,我所做的是,如果用户选择隔天提醒,我在一个循环中创建多个通知。但只有我在循环中的第一个通知被解雇,如果更改系统日期和时间来检查下一个通知,它不起作用。我在这里添加我的代码,如果我做错了什么,请有人纠正我。
func scheduleNotification(_ notification: Notification) {
let content = UNMutableNotificationContent()
content.body = Constants.notificationDescription
content.title = notification.title
content.sound = .default
content.userInfo = ["id":notification.id]
content.categoryIdentifier = Constants.notificaitonCategoryIdentifier
// Notification Actions
let takenAction = UNNotificationAction(identifier: Constants.notiTakenActionIdentifier, title: Constants.notificationTakenText)
let notTakenAction = UNNotificationAction(identifier: Constants.notiNotTakenActionIdentifier, title: Constants.notificationNotTakenText)
let actionCategory = UNNotificationCategory(identifier: Constants.notificaitonCategoryIdentifier, actions: [takenAction, notTakenAction], intentIdentifiers: [])
UNUserNotificationCenter.current().setNotificationCategories([actionCategory])
var dateComponents = DateComponents()
if notification.frequency == .daily {
dateComponents.hour = notification.hour
dateComponents.minute = notification.min
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let nextTriggerDate = trigger.nextTriggerDate()
let request = UNNotificationRequest(
identifier: notification.id,
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request)
} else if notification.frequency == .weekly {
dateComponents.hour = notification.hour
dateComponents.minute = notification.min
dateComponents.weekday = notification.weekDay
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let nextTriggerDate = trigger.nextTriggerDate()
let request = UNNotificationRequest(
identifier: notification.id,
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request)
} else if notification.frequency == .alternateDay {
let firstDate = notification.date
for i in stride(from: 0, to: 30, by: 2) {
guard let date = Calendar.current.date(byAdding: .day, value: i, to: firstDate) else {return}
let dateComponents = date.getDateComponents()
print(date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
/*let timeInterval = Double(120 + (i * 120))
print(timeInterval)
let timeTrigger = UNTimeIntervalNotificationTrigger(timeInterval: timeInterval, repeats: false)
print(timeTrigger.nextTriggerDate())*/
let request = UNNotificationRequest(
identifier: notification.id + String(i),
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
self.getPendingRequests()
}
}
在这里,我使用stride在每次迭代中添加2天,当我使用print语句检查日期时,所有日期都被打印出来并且是正确的,但是除了第一个通知之外,没有出现通知。先谢了。
编辑:
extension Date {
public func getDateComponents() -> DateComponents {
let dateComponents = Calendar.current.dateComponents([.hour, .minute, .second, .day], from: self)
return dateComponents
}
}
1条答案
按热度按时间yqkkidmi1#
你通常在正确的轨道上,但有一对夫妇的问题,您的实施为交替天。
1.我假设你希望隔日服药提醒也重复,就像你每天和每周的提醒一样。如果这是正确的,即使你的示例代码工作,隔日提醒将触发15次,然后停止。
1.我认为另一个问题是你使用
Date.getDateComponents()
扩展函数来获取日期组件。由于您没有提供如何实现,因此可能存在问题。根据documentation,您应该只提供与触发器相关的日期组件。您可能没有返回正确的组件集,或者返回的组件比您需要的多。这可能就是为什么它不工作。1.即使您的扩展函数
Date.getDateComponents()
获取了正确的日期组件,实现一个重复的基于格里高利历的通知触发器也是极其困难的。这是因为对于每隔一天的频率,几乎没有重复:相对而言,一周中的每一天和一个月中的每一天都不重复。几个月你会在偶数天,几个月你会在奇数天。你几乎需要一个特殊的日历,每周定义为14天。在那个假想的日历中,一周中的每一天都是重复的。我们该何去何从?在我看来,你有两个现实的选择。
1.您计算接下来n年(您定义n)的隔日频率的日历日。并在计算中的每一天向
UNUserNotificationCenter
提交一次性/非重复请求。然而,这可能有一些限制。操作系统可能不会让你安排那么多一次性/非重复的通知到未来,以防止各种应用程序的滥用。所以你必须绕过这个限制,如果存在的话。1.您可能已经注意到,UNUserNotificationCenter.add(request)函数接受一个可选的完成处理程序。在您的示例中,您将
nil
传递给它。您可以编写完成处理程序,以便在触发完成处理程序时,代码将下一个预定触发器提交给UNUserNotificationCenter。这就像雏菊链。在这种情况下,您可能需要处理计划通知未触发的情况,例如,当用户的设备关闭时。但这种方法可能会让你更接近你想要的东西。