如何在iOS Swift中安排多个本地通知?

mtb9vblg  于 12个月前  发布在  iOS
关注(0)|答案(1)|浏览(144)

我正在开发一个药物提醒应用程序,用户可以在其中添加每日,每周或隔日的药物提醒,并选择提醒时间。这是一个简单的实现每天和每周,但我很难找到一个解决方案,为交替的日子,因为苹果不提供任何选项,通过频率值与日历通知触发。我在网上找遍了,但没有找到任何解决办法。到目前为止,我所做的是,如果用户选择隔天提醒,我在一个循环中创建多个通知。但只有我在循环中的第一个通知被解雇,如果更改系统日期和时间来检查下一个通知,它不起作用。我在这里添加我的代码,如果我做错了什么,请有人纠正我。

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
    }
}
yqkkidmi

yqkkidmi1#

你通常在正确的轨道上,但有一对夫妇的问题,您的实施为交替天。
1.我假设你希望隔日服药提醒也重复,就像你每天和每周的提醒一样。如果这是正确的,即使你的示例代码工作,隔日提醒将触发15次,然后停止。
1.我认为另一个问题是你使用Date.getDateComponents()扩展函数来获取日期组件。由于您没有提供如何实现,因此可能存在问题。根据documentation,您应该只提供与触发器相关的日期组件。您可能没有返回正确的组件集,或者返回的组件比您需要的多。这可能就是为什么它不工作。
1.即使您的扩展函数Date.getDateComponents()获取了正确的日期组件,实现一个重复的基于格里高利历的通知触发器也是极其困难的。这是因为对于每隔一天的频率,几乎没有重复:相对而言,一周中的每一天和一个月中的每一天都不重复。几个月你会在偶数天,几个月你会在奇数天。你几乎需要一个特殊的日历,每周定义为14天。在那个假想的日历中,一周中的每一天都是重复的。
我们该何去何从?在我看来,你有两个现实的选择。
1.您计算接下来n年(您定义n)的隔日频率的日历日。并在计算中的每一天向UNUserNotificationCenter提交一次性/非重复请求。然而,这可能有一些限制。操作系统可能不会让你安排那么多一次性/非重复的通知到未来,以防止各种应用程序的滥用。所以你必须绕过这个限制,如果存在的话。
1.您可能已经注意到,UNUserNotificationCenter.add(request)函数接受一个可选的完成处理程序。在您的示例中,您将nil传递给它。您可以编写完成处理程序,以便在触发完成处理程序时,代码将下一个预定触发器提交给UNUserNotificationCenter。这就像雏菊链。在这种情况下,您可能需要处理计划通知未触发的情况,例如,当用户的设备关闭时。但这种方法可能会让你更接近你想要的东西。

相关问题