5

Using new local notifications from UNUserNotificationCenter. I try to delete notification with some identifiers:

UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: identifiers)

and from documention:

This method executes asynchronously, removing the pending notification requests on a secondary thread.

Completion handler is not present. So how do I know when its really get deleted? Before moving ahead, I need to make sure that this identifier is not present anymore.

I know I can use next code

notificationCenter.getPendingNotificationRequests { (requests) in
        for request in requests {
         }
}

But if I run this code right after removing - they are still there. But after some time and later in the code they are gone. Especially its important before adding new one when you re about to rich the limit of 64 notifications

Igor Lantushenko
  • 1,771
  • 10
  • 19

2 Answers2

0

You don't have to do all that complex logic as you posted in your answer. You can simply call removeAllPendingNotificationRequests and wait for when it's done within getPendingNotificationRequests method. You can run this code below and see what happens. You will see that after remove will be printed immediately then numbers from 1..63 and then 0.

let notificationCenter = UNUserNotificationCenter.current()

    for i in 1 ... 63 {
        let components: Set<Calendar.Component> = [.year, .month, .day, .hour, .minute, .second]

        let date = Calendar.current.date(byAdding: .hour, value: 1, to: Date())!

        let dateComponents = Calendar.current.dateComponents(components, from: date)

        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

        let content = UNMutableNotificationContent()

        content.title = "Title"
        content.body = "Body"
        content.sound = UNNotificationSound.default()

        let request = UNNotificationRequest(identifier: "id" + String(i),
                content: content, trigger: trigger)

        notificationCenter.add(request) {
            (error) in

            print(i)
        }
    }

    notificationCenter.removeAllPendingNotificationRequests()

    print("after remove")

    notificationCenter.getPendingNotificationRequests() {
        requests in
        print(requests.count)
    }

The reason why it works so is that because all them are tasks put into the queue and run one by one. So, first, it puts 63 notifications, then it removes them, and finally, it counts them. All those tasks go strictly one after each other

Next Developer
  • 1,249
  • 1
  • 10
  • 20
-2

Ok looks like after awhile I found one of the ways - its DispatchGroup Its done also in async way with userInteractive quality:

let dq = DispatchQueue.global(qos: .userInteractive)
dq.async {
    let group  = DispatchGroup()
    group.enter()
    UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: arr)
group.leave()

    group.notify(queue: DispatchQueue.main) { () in
        UNUserNotificationCenter.current().getPendingNotificationRequests { (requests) in
            for request in requests {
                print("||=> Existing identifier is \(request.identifier)")
            }
        }
    }        
}

And that deleted notifications does not exist in getPendingNotificationRequests

Igor Lantushenko
  • 1,771
  • 10
  • 19
  • 2
    I think it doesn't work because removePendingNotificationRequests will still be run on the different thread and therefore the group will leave immediately. It would work if group.leave was called in thread where removePendingNotificationRequests is – Next Developer Sep 26 '17 at 19:21