この質問はUserNotifications
、iOS 10 の新しいフレームワークに関するものです。
ユーザーがアプリで特定のアクションを実行した後、1 時間から 30 分ごとにローカル通知をスケジュールするアプリがあります。
ユーザーのロック画面や通知センターが煩雑になるのを避けるために、一度に表示される通知は 1 つだけにして、最新の関連情報を含む通知が 1 つだけになるようにします。これを達成するための私の計画は、新しい通知が表示されるたびに、配信されたすべての通知をクリアすることです。
willPresent
の新しいメソッドでこれが可能になるはずですがUNUserNotificationCenterDelegate
、期待どおりに動作していません。
アプリでのイベントの 1 時間後に開始し、イベントの 23.5 時間後の最後の通知まで 30 分ごとに通知をスケジュールする、すべての通知を設定するために呼び出す関数を次に示します。
func updateNotifications() {
for hour in 1...23 {
scheduleNotification(withOffsetInHours: Double(hour))
scheduleNotification(withOffsetInHours: Double(hour) + 0.5)
}
}
これは、他の場所で設定されている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
「表示されます...」が出力されるため、関数が呼び出されていることはわかっていますが、通知センターの既存の通知はクリアされません。これが機能しない理由を誰かが知っていますか?または、希望どおりに機能させる方法がある場合は?
編集:同じことを達成するための別のアプローチを思いつきましたが、それもうまくいかないようです。
ここでの私の考えはwillPresent
、別の通知がすぐに (トリガーなしで) 到着するようにスケジュールしながら、スケジュールされた着信通知を無音にするために使用することでした。すぐに到着するようにスケジュールされているすべての通知は同じ識別子を持つため、この 2016 WWDCの新しい 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])
}
}
編集:このページの上部にあるように、アプリがフォアグラウンドにある場合にwillPresent
のみ呼び出されることに最終的に気付きました。したがって、これらのアプローチはどちらも実際には機能しません。通知を受け取るたびに呼び出されると思いました。この「最新の、最も関連性の高い通知のみ」というアイデアの設計図に戻ります...willPresent
更新 (2018 年 7 月): iOS 12 でグループ化された通知が導入されたため、(通知の煩雑さを減らすことを目的として) 古い通知を更新することはあまり重要ではないようです。混乱の出現を最小限に抑えるためにそれを実行できるようにしたいのですが、事後に更新できるリモートプッシュ通知と、後で更新できないローカル通知の間に機能の同等性があるはずです. ただし、Apple はグループ化された通知を導入したため、古いローカル通知を更新する機能を実装して、アプリが新しい通知を送信し、既存の通知と一緒にグループ化できるようにする可能性は低いと思います。