这个问题是关于iOS 10中的新 UserNotifications
框架 .
我有一个应用程序,在用户在应用程序中执行某个操作后,每隔半小时安排一次本地通知,从1小时开始 .
为了避免使用户的锁定屏幕或通知中心混乱,我只希望一次显示一个通知,因此只有一个通知包含最新的相关信息 . 我实现这一目标的计划是在出现新通知时随时清除所有已发送的通知 .
看来这应该可以使用 UNUserNotificationCenterDelegate
的新 willPresent
方法,但它的行为并不像我期望的那样 .
这是一个函数,我打电话设置所有通知,从应用程序中的事件后1小时开始,并在事件发生后23.5小时每隔半小时安排一次通知,直到最后一个通知:
func updateNotifications() {
for hour in 1...23 {
scheduleNotification(withOffsetInHours: Double(hour))
scheduleNotification(withOffsetInHours: Double(hour) + 0.5)
}
}
这是实际根据 mostRecentEventDate
调度通知的函数, mostRecentEventDate
是在别处设置的 Date
:
func scheduleNotification(withOffsetInHours: Double) {
// set up a Date for when the notification should fire
let offsetInSeconds = 60 * 60 * withOffsetInHours
let offsetFireDate = mostRecentEventDate.addingTimeInterval(offsetInSeconds)
// set up the content of the notification
let content = UNMutableNotificationContent()
content.categoryIdentifier = "reminder"
content.sound = UNNotificationSound.default()
content.title = "Attention!"
content.body = "It has been \(withOffsetInHours) hours since the most recent event."
// set up the trigger
let triggerDateComponents = Calendar.current.components([.year, .month, .day, .hour, .minute, .second], from: offsetFireDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDateComponents, repeats: false)
// set up the request
let identifier = "reminder\(withOffsetInHours)"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
// add the request for this notification
UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in
if error != nil {
print(error)
}
})
}
在我的 UNUserNotificationCenterDelegate
中,我将 willPresent
方法设置如下:
func userNotificationCenter(_: UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {
print("will present...")
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
withCompletionHandler([.alert,.sound])
}
我知道正在调用 willPresent
函数,因为它打印"will present..."但通知中心的现有通知不起作用?或者,如果有办法让它以我想要的方式运作?
EDIT: 我提出了另一种方法来实现同样的目的,但它似乎也没有用 .
我的想法是使用 willPresent
来静音传入的预定通知,同时安排另一个通知立即到达(没有触发器) . 计划立即到达的所有通知都具有相同的标识符,因此应始终替换具有该标识符的现有通知,例如在this 2016 WWDC talk中关于新UserNotifications框架的20:00左右的示例中 . 这是我更新的 willPresent
方法:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {
let identifier = willPresent.request.identifier
if identifier != "reminder" {
let offsetInHoursString = identifier.replacingOccurrences(of: "reminder", with: "")
let content = UNMutableNotificationContent()
content.categoryIdentifier = "reminder"
content.sound = UNNotificationSound.default()
content.title = "Attention!"
content.body = "It has been \(offsetInHoursString) hours since the most recent event."
let identifier = "hydrationReminder"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: nil)
center.add(request, withCompletionHandler: { (error) in
if error != nil {
print(error)
}
})
withCompletionHandler([])
} else {
withCompletionHandler([.alert,.sound])
}
}
EDIT: 我终于意识到 willPresent
只会在应用程序位于前台时被调用,正如它在this page的顶部所说的那样,所以这些方法都不应该真正起作用 . 我以为每次收到通知都会调用 willPresent
. 回到这个"only the newest, most relevant notification"想法的绘图板......
UPDATE (July 2018): 随着iOS 12中分组通知的引入,更新旧通知(目标是减少通知混乱)似乎不太相关 . 我希望它们不太可能实现更新旧的本地通知的能力,而是让应用程序只发送新的通知并让它们与现有通知组合在一起 .
2 回答
你可以查看demo .
我想你想实现的功能叫做“更新通知” .
iOS 10允许更新通知 . 您只需执行 - 保持通知具有相同的 identifier .
我们来看一个演示:
现在,你添加了两个通知 . 但系统将它们视为相同 . 所以只有一个 . 而sencond取代了第一个 . 在iOS 10中,调用它 update .
属性“identifier”是UNNotificationRequest的id,可以区分通知 .
你可以使用removeDeliveredNotifications(withIdentifiers:)