Удаление запланированного локального уведомления - PullRequest
1 голос
/ 22 апреля 2020

Я знаю, что есть много похожих вопросов и ответов, и я просмотрел их все, но все еще не могу найти решение. Несмотря на удаление запланированного уведомления из UNUserNotificationCenter, оно все равно срабатывает.

Я создаю локальное уведомление следующим образом:

let aDF = DateFormatter()
aDF.dateFormat = "yyyy-MM-dd HH:mm:ss"
var identifierST = ""
    if update == true {
        identifierST = myCoreDataEntity.notificationUID!
    } else {
        identifierST = aDF.string(from: Date())
    }

let notif = UNMutableNotificationContent()
notif.title = "some string"
notif.body = "some string"
var dateComp: DateComponents
switch myCoreDataEntity.schedule {
case 1: //daily
    dateComp = Calendar.current.dateComponents([.hour, .minute], from: myCoreDataEntity.date)

case 2: //weekly
    dateComp = Calendar.current.dateComponents([.weekday, .hour, .minute], from: myCoreDataEntity.date)

case 3: //monthly
    dateComp = Calendar.current.dateComponents([.day, .hour, .minute], from: myCoreDataEntity.date)

case 4: //quartely - this is actually not quarterly, dont know how to set quarterly, setting monthly
    dateComp = Calendar.current.dateComponents([.day, .hour, .minute], from: myCoreDataEntity.date)

case 5: //halfyearly - this is actually not halfyearly, dont know how to set halfyearly, setting monthly
    dateComp = Calendar.current.dateComponents([.day, .hour, .minute], from: myCoreDataEntity.date)

case 6: //yearly
    dateComp = Calendar.current.dateComponents([.month, .day, .hour, .minute], from: myCoreDataEntity.date)

default: //monthly
    dateComp = Calendar.current.dateComponents([.day, .hour, .minute], from: myCoreDataEntity.date)

}
dateComp.hour = 10
dateComp.minute = 0

let notificationTrigger = UNCalendarNotificationTrigger(dateMatching: dateComp, repeats: true)
        let request = UNNotificationRequest.init(identifier: timeStampST, content: notif, trigger: notificationTrigger)
        UNUserNotificationCenter.current().add(request) { (error) in
            if (error != nil) {
                 print (error) //notify user that reminder was not saved
            } else {
                 myCoreDataEntity.notificationUID = identifierST
            }
        }

notificationUID - это строковый атрибут в объекте CoreData, в котором я храню созданный идентификатор уведомления, поэтому я могу получить его позже.

Вышеуказанное работает правильно, уведомление запланировано и доставлено в определенные дату и время, поэтому здесь нет проблем.

Всякий раз, когда мне нужно удалить конкретное уведомление, я получаю сохраненный идентификатор уведомления (notificationUID) и передать его следующей функции:

func removeExisting(identifierST: String) {
     UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [identifierST])
}

При попытке найти проблему я получил все ожидающие уведомления и сравнил их identifiers с identifierST, который я передаю removePendingNotificationRequests, и они match

UNUserNotificationCenter.current().getPendingNotificationRequests(completionHandler: { requests in
        for request in requests {
            print("==============================================")
            print(request.identifier)
            print(request.content.title)
            print(request.content.subtitle)
            print(request.content.body)
        }
})

Но эти отмененные уведомления все еще запускаются, я что-то упускаю здесь очевидное?

Редактировать 1

Чтобы предоставить немного подробнее о логике приложения c и сценарии ios:

  • Приложение создает некоторые события, повторяющиеся ежедневно, еженедельно, ежемесячно и т. д. c

  • для каждого событие создается уведомление

  • Уведомление отправляется в день события

  • Пользователь может видеть предстоящие события и может выбрать пропустить один цикл => вот в чем проблема -> когда пользователь решил пропустить, я запускаю func removeExisting(identifierST: String), чтобы удалить его, но когда наступает дата этого пропущенного события, уведомление все еще отправляется.

Редактировать 2

Re: ошибка возможной опечатки или лога c при удалении уведомления - причина, по которой я уверен, что ошибки нет, заключается в том, что это работает, когда я не пропускаю и не редактирую событие, но удаляю его, то есть предположим, что дата события - завтра, а уведомление планируется доставить завтра в 10:00. Сегодня пользователь решает, что он вообще не хочет этого, и удаляет его, поэтому я запускаю func removeExisting(identifierST: String), и это работает -> завтра не генерируется уведомление об этом событии.

Но, если пользователь решает не удалять полностью, а просто пропустить 1 день завтра и продолжить с послезавтра (в случаях, когда расписание является ежедневным), это - то, где я получаю проблему. Я пытался рассмотреть этот сценарий в 3 подходах:

Подход 1 - Удалить существующее уведомление и создать новое с новым идентификатором и новой датой запуска - послезавтра

Подход 2 - Создать уведомление с тем же идентификатором (при условии, что это не создаст новый, но изменит существующий), но с новой датой запуска - послезавтра

Подход 3 - Удалить существующее уведомление и создать новое с тем же идентификатором и новой датой запуска - послезавтра

Ничего из этого не работает.

Ответы [ 3 ]

1 голос
/ 27 апреля 2020

Сначала позвольте мне объяснить, почему то, что вы делаете, не работает.

Допустим, у вас много разных дат, например: 27 апреля, 4 мая, 11 мая, 18 мая и c ..

Вы присваиваете dateComp как

dateComp = Calendar.current.dateComponents([.weekday, .hour, .minute], from: myCoreDataEntity.date)

, поэтому для каждой из упомянутых дат ваш dateComp будет выглядеть так:

dateComp = [Monday, 10, 30] // April 27th
dateComp = [Monday, 10, 30] // May 4th
dateComp = [Monday, 10, 30] // May 11th
dateComp = [Monday, 10, 30] // May 18th

и затем вы добавите это dateComp в вашем триггере, вы видите, куда я иду с этим? Триггер не имеет ничего общего с вашей датой, за исключением этих трех параметров, изменяя дату неделю спустя, вы фактически используете точно такой же триггер.

В момент добавления вашего запроса в центр уведомлений ваше уведомление настроен на показ в СЛЕДУЮЩЕМ ДОСТУПНО в понедельник в 10:30, а НЕ в вашу дату Понедельник 10: 30.

У меня была такая же проблема, и я разместил здесь аналогичный вопрос. Из всех моих исследований и того, что говорили другие, невозможно настроить повторное уведомление от указанной c будущей даты в текущем UNNotificationCenter, я буду более чем счастлив, если кто-то может доказать, что я неправ по этому поводу.

Вы может установить целую датуComp из вашей даты, например [.month, .day, .hour, .minute], но затем, если вы установите для repeat значение true, оно будет повторяться только в том же [.month, .day, .hour,. минуты], что в конечном итоге будет повторяться ежегодно.

Решением может быть либо установка неповторяющегося уведомления для каждой указанной c даты (существует ограничение в 64 уведомления, которые вы можете получать одновременно), либо т.п. в моем случае настройте семь повторяющихся уведомлений для каждого дня недели, а затем просто удалите одно, которое вам не нужно, и добавьте его снова в другой день, но НЕ в тот же день, потому что оно будет запущено снова.

Вы можете проверить код, который я использовал в своем приложении, чтобы сделать это здесь:

Как настроить ежедневное локальное уведомление для задач, но не шо когда пользователь завершит задачу до

0 голосов
/ 25 апреля 2020

Я сейчас снова посмотрел связанное с WWD C видео - https://developer.apple.com/videos/play/wwdc2016/707 - и немного изменил логику c.

Оригинальный подход

Когда пользователь пропускает цикл, я удаляю запланированное уведомление и создаю новое, с новым идентификатором и новой датой запуска.

Новый подход

Когда пользователь пропускает цикл, я ничего не удаляю, но создаю «новое» уведомление с новой датой запуска, но использую ту же идентификатор. Как я понимаю из видео, использование одного и того же идентификатора фактически не создает новое уведомление, а обновляет существующее. Я смогу подтвердить, работает ли это через 24 часа.

0 голосов
/ 25 апреля 2020

Вы имеете в виду, что вы вызываете getPendingNotificationRequests и больше не видите тот, который вы удалили? Тогда вы уверены, что код для добавления не вызывается случайно после этого? (так что это может быть добавлено снова?)

Одна особенность UNUserNotificationCenter.current().add() заключается в том, что, если уведомление с желаемым идентификатором уже запланировано, оно не будет планировать другое уведомление в то же время, но оно будет Также не выдают ошибку. Вы можете думать об этом как о том, что он перезаписывает существующий. Итак, если ваш код каким-то образом снова и снова планирует одни и те же уведомления, вы, вероятно, не заметите. Пока вы не попытаетесь удалить уведомления, а затем они будут перенесены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...