swift - 每 X 天本地通知 - Swift
问题描述
在我开始之前,请不要烧我,因为我知道这已经被问了数百次,没有可靠的答案,但我相信有一个使用后台刷新的解决方案。https://medisafe.com/ app 似乎已经解决了!
目标:每 x 天在指定时间触发本地通知
我的解决方案
第 1 步:从开始日期和奇数发生(本例 2)天(已编辑)获取计时器间隔
第 2 步:在此差异上设置间隔计时器并重复
第 3 步:激活后台刷新(如果应用程序甚至被终止,它将在后台加载应用程序并给我一个小窗口来执行一些任务)
step 4. 设置后台刷新每天触发一次
第 5 步:执行 get items api,它将刷新所有计时器和通知
步骤 6 坐下来,对我的解决方案感到惊讶地微笑
但这失败了。
所以一个计时器间隔
let newTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 172800,repeats: true)
但这只会在每天执行后台获取时重置计时器,它将从现在触发 2 天,而不是从开始日期触发。
因此,必须有一种比较日期小时和分钟(开始日期、x 日期和当前日期)的方法来计算计时器间隔值。
目前我正在使用日历组件。触发每天即时执行以下操作
var triggerType : DateComponents? {
var triggerT : DateComponents?
var cal = Calendar(identifier: .gregorian)
cal.firstWeekday = 2
if let notificationModel = self.notificationModel {
switch notificationModel.reminderType {
case .daily?, .weekly?:
if let date = notificationModel.date {
triggerT = cal.dateComponents([.weekday, .hour, .minute], from:date)
if let weekday = notificationModel.weekday {
triggerT?.weekday = weekday
}
}
case .alternateDays?:
if let date = notificationModel.date {
triggerT = cal.dateComponents([ .hour, .minute], from:date)
// THIS IS WHERE I NEED HELP
}
case .monthly?:
if let date = notificationModel.date {
triggerT = cal.dateComponents([.day,.hour,.minute], from: date)
}
case .yearly?:
triggerT = Calendar.current.dateComponents([.month,.day,.hour,.minute], from: (notificationModel.date)!)
case .oneOff?:
triggerT = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute], from: (notificationModel.date)!)
case .none:
DispatchQueue.main.async {
if let category = self.notificationModel?.category, let title = self.notificationModel?.title {
Toast.down("An error was discovered in \(category). Please change the occurance value for the following \(title)")
}
}
}
} else {
print("NOTIFICATION MODEL IS CORRUPT")
}
return triggerT
}
func add(notification: NotificationModel){
let content = UNMutableNotificationContent()
if let title = notification.title,
let body = notification.body,
let identifier = notification.identifier {
content.title = title
content.body = body
content.sound = UNNotificationSound.default()
content.categoryIdentifier = (notification.category?.rawValue)!
content.setValue("YES", forKeyPath: "shouldAlwaysAlertWhileAppIsForeground")
var trigger : UNCalendarNotificationTrigger?
if let triggerType = self.triggerType {
if let occurance = notification.occurance {
if occurance > 0 {
}
}
trigger = UNCalendarNotificationTrigger(dateMatching: triggerType, repeats: true)
} else {
return
}
let interval = Date().timeIntervalSince1970
let identifierString = "2\(interval)"
var request : UNNotificationRequest!
if notification.reminderType == .alternateDays {
print("ADDING TIMER NOTIFICATION")
print("REMINDER TIME = \(notification.date)")
// 172800 = two days
let newTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 172800,
repeats: true)
request = UNNotificationRequest(identifier: identifierString,
content: content, trigger: newTrigger)
} else {
request = UNNotificationRequest(identifier: identifierString,
content: content, trigger: trigger)
}
center.add(request, withCompletionHandler: { (error) in
if let error = error {
// Something went wrong
print(error.localizedDescription)
} else
{
print("ADDING NOTIDCIATION \(content.title)")
}
})
//SNOOZE OR DELETE NOTIFICATIONS
let snoozeAction = UNNotificationAction(identifier: "Snooze", title: "Snooze", options: [])
let deleteAction = UNNotificationAction(identifier: "UYLDeleteAction",title: "Delete", options: [.destructive])
//Create a category with the actions: This requires another unique identifier (you probably want to define these magic strings in an enum):
let category = UNNotificationCategory(identifier: notification.category!.rawValue,
actions: [snoozeAction,deleteAction],
intentIdentifiers: [], options: [])
//Register the category with the notification center. It is recommended to do this early in the app lifecycle.
center.setNotificationCategories([category])
//To include this action in our notifications we need to set the category in the notification content:
} else {
print("Failed to add notification")
}
}
但是,我想要每隔一天,不想使用 64 通知限制。
谢谢你的时间
托马斯
解决方案
假设您想在 2、4 和 6 天后触发通知,您可以这样做:
对于我的示例,我添加了扩展名Date
extension Date {
func adding(days: Int) -> Date? {
var dateComponents = DateComponents()
dateComponents.day = days
return NSCalendar.current.date(byAdding: dateComponents, to: self)
}
}
然后你可以为指定的日期创建新的通知,在这个例子中是从现在开始的 2、4、6 天
let date = Date()
for i in [2, 4, 6] {
if let date = date.adding(days: i) {
scheduleNotification(withDate: date)
}
}
func scheduleNotification(withDate date: Date) {
let notificationContent = UNMutableNotificationContent()
notificationContent.title = "Title"
notificationContent.subtitle = "Subtitle"
notificationContent.body = "Body"
let identifier = "Make up identifiers here"
let dateComponents = Calendar.autoupdatingCurrent.dateComponents([.day, .month, .year, .hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let notificationReques = UNNotificationRequest(identifier: identifier, content: notificationContent, trigger: trigger)
UNUserNotificationCenter.current().add(notificationReques) { error in
if let e = error {
print("Error \(e.localizedDescription)")
}
}
}
这应该安排 3 个通知 - 从现在起 2、4、6 天......
推荐阅读
- php - 允许客户在 WooCommerce 我的帐户中更改订单状态
- java - 如何暂停整个程序的执行,直到在 JAVA 中按下按钮?
- google-cloud-storage - 如何使用访问密钥将 PUT 放入谷歌存储桶?
- vb.net - 将 COM 服务导入 VB.net
- c - 是否可以从头文件中输出变量?
- c# - C#如何按字符串值对对象字符串进行排序
- javascript - 如何使用依赖下拉列表 Django + JS 进行搜索?
- java - 河豚加密和解密不起作用
- apache-camel - 用于多个文件处理的骆驼
- sql - 使用 ORDER BY NEWID() 生成随机测试数据,包括重复行