Повторения в UserNotifications

swift

#1

Всем привет! Изучаю Swift на примере создания приложения напоминаний. Есть задача показывать напоминания о просроченных задачах пользователю. С однократным напоминанием разобрался, посмотрев курс. Вопрос возник о многократных напоминаниях. Речь не о том, чтобы повторять напоминания (каждый день, неделю, месяц и т.д.). Как я понял, то параметр repeats отвечает за это. А речь о том, чтобы повторять одно и то же напоминание постоянно, пока пользователь не просмотрит его. к примеру, сработало напоминание по дате и времени. Пользователь не смотрит на него. Через 5 минут(к примеру) оно повторяется еще раз. И так до тех пор, пока пользователь не просмотрит, либо не нажмет какую-либо кнопку действия. Такое возможно в UserNotifications “из коробки”?


#2

Если я не ошибаюсь, то нет. Возможно более опытные коллеги меня поправят.


#3

Вот, ищу на разных форумах ответ. Везде ограничиваются простым примером однократного уведомления. У меня есть одно приложение на телефоне. Тоже напоминания. Там можно в настройках выбрать “Повторять бесконечно”. Вот тут я не особо понимаю как можно так сделать. Идея относительно фиксированного количество повторений такая: создавать по каждой задаче 5(например) уведомлений, начиная с нужно даты, с нужным интервалом. В качестве идентификатора использовать ключ, состоящий из основного идентификатора и номера уведомления. Т.к. номера уведомлений известны, то при появлении любого из этих уведомлений и нажатии пользователем како-го либо действия(скажем, “завершит”) очищать все ждущие уведомления по основному идентификатору и номерам уведомлений. При выборе “отложить”, также, очищать те, что в ожидании и добавлять еще пул из 5 уведомлений. Но как сделать бесконечные уведомление(пока пользователь не отреагирует - будут появляться) - ума не приложу.


#4

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


#5

Думаю, Вы правы. Буду копать в эту сторону. Спасибо!


#6

Я сделал по-простому (учусь пока ;):

  1. Отправляю уведомление в очередь с необходимой датой/временем показа при создании задачи или чего вам надо.
  2. Сравниваю сегодняшнюю дату/время с датой/временем появления уведомления. Если не наступило, то ничего - уведомление то стоит в очереди на нужную дату. Если наступило то на всякий случай удалили прошлое уведомление и отправляете уведомление на нужное время с интервальным повтором.
  3. Как только пользователь посмотрел - удалили повторяемое уведомление.

Если пригодится, вот extension формата Date для сравнения двух дат.

extension Date {
    func daysBetweenDate(toDate: Date) -> Int {
        let components = Calendar.current.dateComponents([.day], from: self, to: toDate)
        return components.day ?? 0
    }
}

#7

А где у Вас происходит п.2? Насколько понимаю, это происходит при открытии приложения(или активации)? Вопрос в том, что пользователь вообще может на открывать приложение. Или оно может быть выгружено. Т.е., входная точка взаимодействия с уведомлениями - событие отображения уведомления. К примеру: пользователь установил триггер на определенную дату и время, закрыл приложение и забыл про него. При наступлении этой даты должны приходить уведомления бесконечно, пока пользователь не выполнит задачу(перенесет, отменит, удалит).


#8

Для этого используется Notifications Service Extension, который работает в background’e


#9

Да, но он работает только для Remote Notifications. An object that modifies the content of a remote notification before it’s delivered to the user.


#10

#11

В Вашем описании также содержится "Во-первых, ваше расширение будет запущено только для уведомлений, которые настроены для отображения на экране предупреждений пользователю. Это означает, что любые тихие уведомления (например, те, которые используются для обновления значков приложений) не будут вызывать ваше расширение.

Во-вторых, словарь входящих уведомлений aps в своей полезной нагрузке должен включать ключ изменяемого содержимого mutable-content со значением 1.

Правильная настройка ваших уведомлений в конечном счете будет зависеть от настройки вашего приложения. Чтобы соответствовать второму условию, в частности, возможно, потребуется внести некоторые изменения в реализацию push-уведомления на стороне сервера. Если вы не используете настраиваемый сервер и вместо этого используете стороннюю службу для реализации push-уведомления, я бы предложил исследовать и почитать их справочную документацию, если вы не можете сделать так, чтобы ваше расширение работало." В описании на офф. странице Apple также сказано о RemoteNotification https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension

Я пробовал использовать это расширение, но точка останова в методе didRecieve на отрабатывает.


#12

Это расширение не дебажится, т.к. вы его не сможете запустить через Xcode. Там же написано, что оно запускается автоматически при получении уведомления, после чего закрывается.
Единственный способ которым я это расширение дебажил, было изменение текста уведомления.


#13

Попробую, спасибо за идею!


#14

Можете тут на форуме найти мою тему как раз по этому расширению. Там у меня был код для дебага. Только цель у меня была другая. Ищите по фразе “Notifications Service Extension”


#15

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


#16

Проверьте конфигурацию у расширения, она должна быть такая же как у основного проекта.


#17

А где ее можно проверить? info.plist?


#18

Расширение - это как отдельный проект, у него свой plist, свои настройки. Там где версия проекта меняется, с левой стороны появится ваше расширение, там и смотрите.


#19

Я понимаю, смотрю Target properties. Содержание у них разное, версии в том числе. Что именно там должно быть одинакового?


#20

Я уже точно не помню, но версии точно должны быть ондинаковыми.