问题描述
所以这是交易。:
更新: 我发现了这个问题,我不知道本地通知有限制,可以安排。我达到了那个极限,并以一种非常安静的方式把最老的扔了出去,就我而言,我一开始就看不到这一点。不确定是否会更好,至少在控制台中抛出警告或在完成块中抛出错误。
我有一组自定义对象 (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 (将#修改为@)