UNCalendarNotificationTrigger 不会在自定义 DateComponents 上触发

问题描述

所以这是交易。:

更新: 我发现了这个问题,我不知道本地通知有限制,可以安排。我达到了那个极限,并以一种非常安静的方式把最老的扔了出去,就我而言,我一开始就看不到这一点。不确定是否会更好,至少在控制台中抛出警告或在完成块中抛出错误。

我有一组自定义对象 (ScheduleItem),它们具有特定日期,特定事件将在该日期发生。

class ScheduleItem: Codable {
    var typeId: Int
    var typeName: String
    var wash: Bool
    var date: Date 
}

用户现在可以参考那个日期来定义他想要接收本地推送通知的时间。时间由时间选择器选择,日期由一组预定义的值(同一天、前一天……)选择。这些选定的值现在存储在 UserDefaults 中。

所以每当我收到数组时,我实际上是在检查待处理的通知,生成不需要的 id 列表,删除它们并使用相同的标识符替换/更新其余的。检查这里的代码片段:

func updateScheduleReminders(_ completion: (() -> ())? = nil) {
    let formatter = DateFormatter()
    formatter.dateFormat = "dd.MM.yyyy"
    
    UNUserNotificationCenter.current().getNotificationSettings() { (status) in
        // get pending identifiers
        let identifiers: [String] = ScheduleManager.sharedInstance.scheduleItems.map { "\($0.typeName) \($0.date)" }
                        
        // delete all pending notifications
        UNUserNotificationCenter.current().getPendingNotificationRequests { (pendingRequests) in
            let toDelete = pendingRequests.filter { !identifiers.contains($0.identifier) }.map { $0.identifier }                    //UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: toDelete)
                
            // register new/replace old notifications
            if status.authorizationStatus == .authorized {
                // create new notifications
                for scheduleItem in ScheduleManager.sharedInstance.scheduleItems {
                    guard
                        let fireDate = scheduleItem.fireDate(),let type = scheduleItem.type()
                    else {
                        continue
                    }
                        
                    let identifier = "\(scheduleItem.typeName) \(scheduleItem.date)"
                    var alertBody = "Body Text"
                    self.scheduleReminder(
                        alertBody,fireDate,type.rawValue,identifier
                     )
                  }
                }
            } else {
                self.removePendingNotifications()
            }
          
            completion?()                    
        }
    }
}

所以这很简单,安排提醒的功能如下

func scheduleReminder(_ body: String,_ fireDate: DateComponents,_ type: String,_ uuid: String) {
    // create local notification
    let content = UNMutableNotificationContent()
    content.userInfo = []
    content.sound = UNNotificationSound.default
    content.body = body
    content.title = "title"
        
    let trigger = UNCalendarNotificationTrigger(dateMatching: fireDate,repeats: false)
    let request = UNNotificationRequest(
        identifier: uuid,content: content,trigger: trigger
    )
        
    // schedule notification
    UNUserNotificationCenter.current().add(request) { (error : Error?) in            
        if let theError = error {
            print("error adding notification \(theError.localizedDescription)")
        }
    }
}

自定义类 ScheduleItem 有一个函数(我知道一个计算属性,看起来会更好,但这不会解决问题:D)来计算触发日期。奇怪的部分来了,请查看我的评论。

func fireDate() -> DateComponents? {
            let calendar = Calendar.current
        
// 1) the first check was returning the same date with a 5 seconds delay,OK!
//        return calendar.dateComponents([.year,.month,.day,.hour,.minute,.second],from: Date().addingTimeInterval(5))

// 2) trying to split the dates up,because this is the way i will have it,works too
//        let scheduleDate = Date()
//        let storedTime = Date().addingTimeInterval(5) 

// 3) having the right code in place does not work
        let scheduledDate = self.date

        guard
            let storedTime = defaults.object(forKey: "storedTime") as? Date
        else {
            return nil
        }

        var dateComponents = calendar.dateComponents([.day,.year],from: scheduleDate)
        let timeComponents = calendar.dateComponents([.hour,from: storedTime)

        dateComponents.hour = timeComponents.hour
        dateComponents.minute = timeComponents.minute
        dateComponents.second = timeComponents.second
        
        return dateComponents
    }

正如代码中的注释已经指出的那样,它适用于 Date() 实例,但在我尝试更改 DateComponents 时不再适用。

到目前为止我做了什么:

  • 注释掉所有不需要的代码
  • 删除了对 cancelPendingNotifications 的任何调用,以确保我不会取消任何通知
  • 删除了对调度函数的并行调用(是的,这是从几个地方调用的)
  • 我没有使用 5 秒到测试日期,而是尝试使用随机值(也可以)
  • 是的,允许通知
  • 在主线程中推送所有内容以排除任何线程问题(如竞争条件等)
  • 调试任何单个日期条目并进行比较
  • 实际上检查了时区,但这应该不是问题,因为我没有从日期组件中提取该信息,对吗?
  • 尝试了所有可能的方法将模拟日期与实际日期相结合(模拟所有日期、仅模拟时间、模拟日期)。一旦我使用 ScheduleItem 实例的真实日期,它就会停止工作

有谁知道,为什么这不能正常工作?现在,我没有想法,任何帮助将不胜感激!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...