title: How can I remove previously delivered notifications when a new notification arrives with UNUserNotificationCenterDelegate in iOS 10?
body: <p>This question is about the new <code>UserNotifications</code> framework in iOS 10.</p>
  
  <p>I have an app that schedules a local notification every half hour after the user did a certain action in the app, starting at 1 hour.</p>
  
  <p>To avoid cluttering a user's lock screen or notification center, I only want one notification to show up at a time, so there is only one notification with the most recent, relevant information. My plan to achieve this is to clear all delivered notifications any time a new notification is presented.</p>
  
  <p>It seems this should be possible with the new <code>willPresent</code> method of <code>UNUserNotificationCenterDelegate</code>, but it's not behaving as I would expect.</p>
  
  <p>Here's a function that I call to set up all the notifications, starting at 1 hour after the event in the app, and scheduling a notification every half hour until the last one at 23.5 hours after the event:</p>
  
  <pre><code>func updateNotifications() {
  
      for hour in 1...23 {
          scheduleNotification(withOffsetInHours: Double(hour))
          scheduleNotification(withOffsetInHours: Double(hour) + 0.5)
      }
  }
  </code></pre>
  
  <p>This is the function that actually schedules the notifications based on the <code>mostRecentEventDate</code>, which is a <code>Date</code> set elsewhere:</p>
  
  <pre><code>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)
          }
      })
  }
  </code></pre>
  
  <p>In my <code>UNUserNotificationCenterDelegate</code> I have the <code>willPresent</code> method set up like this:</p>
  
  <pre><code>func userNotificationCenter(_: UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -&gt; Void) {
  
      print("will present...")
  
      UNUserNotificationCenter.current().removeAllDeliveredNotifications()
  
      withCompletionHandler([.alert,.sound])
  }
  </code></pre>
  
  <p>I know the <code>willPresent</code> function is being called because it prints "will present..." but the existing notifications in the notification center don't get cleared. Does anyone know why this doesn't work? Or if there's a way to get it working the way I want it to?</p>
  
  <hr>
  
  <p><strong>EDIT:</strong> I came up with an alternate approach to achieve the same thing, but it also doesn't seem to work.</p>
  
  <p>My idea here was to use <code>willPresent</code> to silence the incoming scheduled notification while scheduling another notification to arrive immediately (without a trigger). All the notifications being scheduled to arrive immediately have the same identifier, so the existing notification with that identifier should always be replaced, like in the example around 20:00 in <a href="https://developer.apple.com/videos/play/wwdc2016/707/" rel="noreferrer">this 2016 WWDC talk</a> about the new UserNotifications framework. Here's my updated <code>willPresent</code> method:</p>
  
  <pre><code>func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -&gt; 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])
      }
  }
  </code></pre>
  
  <hr>
  
  <p><strong>EDIT:</strong> I finally realized that <code>willPresent</code> will <em>only</em> be called if the app is in the foreground, as it says right at the top of <a href="https://developer.apple.com/reference/usernotifications/unusernotificationcenterdelegate/1649518-usernotificationcenter" rel="noreferrer">this page</a>, so neither of these approaches should actually work. I thought <code>willPresent</code> would be called every time a notification was received. Back to the drawing board on this "only the newest, most relevant notification" idea...</p>
  
  <hr>
  
  <p><strong>UPDATE (July 2018):</strong> With the introduction of grouped notifications in iOS 12, updating an older notification (with the goal of reducing notification clutter) seems less relevant. I'd still like to be able to do it to minimize the appearance of clutter, and it seems there should be feature parity between remote push notifications, which can be updated after the fact, and local notifications, which can not be updated later. However, since Apple has introduced grouped notifications, I'd expect its less likely they'd implement the ability to update old local notifications in favor of letting apps just send new ones and having them group together with existing notifications.</p>