Главная » Хабрахабр » iOS 12: новинки в уведомлениях

iOS 12: новинки в уведомлениях

Были ключевые темы, которым Apple уделила особое внимание. Конференция WWDC прошла, а докладов, которые стоит посмотреть, осталось ещё очень много. Core ML, Siri Shortcuts и, конечно же, изменения в Notifications.

Читйте, осознавайте и внедряйте в свои приложения. Так как не у всех найдётся достаточно свободного времени, чтобы пробираться через дебри документации, которая, как это обычно бывает, на стадии бета-тестирования оставляет желать лучшего, я подготовил обзор новых возможностей и подкрепил материал практической реализацией.

Начнём с обзора возможностей, которые добавила Apple.

Группировка уведомлений

iOS 12 автоматически сгруппирует сообщения за вас. Для реализации ничего делать не нужно. Но есть нюансы, которые касаются кастомизации, локализации и группировки, но не на основе идентификатора приложения, а, например, в зависимости от имени пользователя, который отправил уведомление.

Например, на экране iPhone 8 для этого нужно разместить 5 и более нотификаций. Кроме того, если вы будете тестировать группировку нотификаций, обратите внимание — они начнут собираться в пачку только в том случае, если единовременно все нотификации не могут поместиться на экране.

Чтобы не перегружать этот материал, я вынес его в отдельный текст, который появится на Хабре в ближайшее время.

Изменения в API NSExtensionContext

Он отвечает за взаимодействие с виджетами, Siri, проигрывание медиаконтента. Следующий пункт — новые возможности для нотификаций и в частности класса NSExtensionContext. Были добавлены два метода и одна переменная: Нас больше интересуют уведомления.

var notificationActions: [UNNotificationAction]

Переменная позволяет во время взаимодействия с уведомлением подменить набор доступных действий:

func dismissNotificationContentExtension()
func performNotificationDefaultAction()

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

Для демонстрации возможностей напишем небольшое приложение.

Сперва добавим в приложение отправку локальных уведомлений:

let actions = [ UNNotificationAction(identifier: "like-action", title: "Like", options: []), UNNotificationAction(identifier: "open-app", title: "Open App", options: []), UNNotificationAction(identifier: "dismiss", title: "Dismiss", options: []),
] let simpleCategory = UNNotificationCategory(identifier: "category-simple", actions: actions, intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([simpleCategory])

  • Создаём несколько действий. Идентификатор позволит различать их при обработке, заголовок кнопки и опции. Например выявит то, что для выполнения действия требуется аутентификация пользователя.
  • Определяем категорию с идентификатором. Идентификатор категории позволяет обрабатывать и отображать различные типы уведомлений по-разному.
  • Последним шагом устанавливаем категорию для центра нотификаций.

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

UNUserNotificationCenter.current().getNotificationSettings { (settings) in guard settings.authorizationStatus == .authorized else { return } let content = UNMutableNotificationContent() content.title = "Cat Title" content.subtitle = "Cat Subtitle" content.body = "Cat Body" content.sound = .default content.categoryIdentifier = "category-simple" let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false) let uuid = UUID().uuidString let request = UNNotificationRequest(identifier: uuid, content: content, trigger: trigger) UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in })
}

  • Проверяем, позволил ли нам пользователь отправлять уведомления.
  • Создаём уведомление с заголовком и текстом и указываем категорию, к которой оно будет относится. В данном случае — "category-simple".
  • Устанавливаем триггер срабатывания через 3 секунды.
  • Заполняем запрос на отправку уведомления. В данном случае в качестве идентификатора используем UUID. Этот идентификатор может понадобиться, если мы захотим отменить запланированное уведомление.
  • Добавляем наш запрос в центр нотификаций.

Он позволяет настроить параметры отображения уведомлений и обработку действий. Далее необходимо добавить в приложение новый таргет Notification Content Extension.

Будет создан plist-файл, ViewController и Storyboard:

В plist-файле нас интересуют следующие ключи:

  • UNNotificationExtensionCategory — название категории, которая будет обрабатываться. Как и ранее, укажем "category-simple".
  • UNNotificationExtensionInitialContentSizeRatio — соотношение высоты уведомления к его ширине. Повлияет на размер уведомления после отображения в полном виде.
  • UNNotificationExtensionUserInteractionEnabled — включаем или отключаем взаимодействие с кастомными контролами. В нашем случае это будет кнопка с сердцем.
  • UNNotificationExtensionDefaultContentHidden — скрывает содержимое нотификации, которое формируется по умолчанию.

В сториборд создаём UIImageView, UILabel для отображения заголовка уведомления и UIButton для взаимодействия с приложением.

Во View Controller'е создаём методы для открытия приложения и скрытия нотификации:

func openApp() { extensionContext?.performNotificationDefaultAction()
} func dismissNotification() { extensionContext?.dismissNotificationContentExtension()
}

Реализуем методы протокола UNNotificationContentExtension.

Первый позволит отобразить необходимый текст:

func didReceive(_ notification: UNNotification) { self.notificationTitleLabel.text = notification.request.content.body
}

В этом же методе выполняется подмена действий с помощью присвоения extensionContext?.notificationActions: Второй нужен для обработки действий от UNNotificationAction.

func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) { switch response.actionIdentifier { case "like-action": let actions = [ UNNotificationAction(identifier: "1-star", title: "★", options: []), UNNotificationAction(identifier: "2-star", title: "★ ★", options: []), UNNotificationAction(identifier: "3-star", title: "★ ★ ★", options: []), ] extensionContext?.notificationActions = actions case "open-app": openApp() default: dismissNotification() }
}

Обработка нажатий на сердце выполняется как обычно, через IBAction:

@IBAction func defaultButtonTapped(_ sender: UIButton) { openApp()
}

Запускаем приложение и смотрим, что у нас получилось:

  • Нажатия от UIButton обрабатываются.
  • Использование UNNotificationAction позволяет заменить доступные для взаимодействия варианты.

Взаимодействие с настройками уведомлений

При тапе на него будет осуществлён вызов метода, который вы можете реализовать в приложении. Следующее нововведение позволяет добавить в настройки уведомлений новый пункт меню. Что нужно сделать для реализации? Например, пользователь может напрямую из системных настроек попасть в ваше приложение и в нём включить только те нотификации, которые он действительно хочет получать.

Во-первых, при авторизации нотификаций добавляем ещё один параметр — providesAppNotificationSettings:

UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound, .providesAppNotificationSettings])

Во-вторых, реализуем метод userNotificationCenter(_:openSettingsFor:) протокола UNUserNotificationCenterDelegate:

extension AppDelegate: UNUserNotificationCenterDelegate { func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) { openSettings() } func openSettings() { let storyboard = UIStoryboard(name: "Settings", bundle: nil) let settings = storyboard.instantiateViewController(withIdentifier: "Settings") window?.rootViewController = settings } }

Provisional Notifications

Поэтому при первом запуске приложения такой выбор ему сделать сложно. Пользователь не всегда понимает, хочет ли он получать уведомления от вашего приложения. Для таких ситуаций Apple предлагает использовать Provisional Authorization. С большой вероятностью он откажется от вашего предложения. authorizationStatus для таких уведомлений, также приходит в приложение со статусом provisional. При запросе авторизации на отправку нотификаций добавляется ещё один параметр — provisional.

UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .provisional])

Однако, чтобы его не беспокоить, приложение помещается в так называемый jail. Пользователь при запуске приложения не получит запрос на авторизацию. На заблокированном экране или в виде баннеров они появляться не будут. Для уведомлений отключены звуки, бейджи; они отображаются только в Notification Center.

Одна полностью заблокирует уведомления или предложит перейти в настройки, а вторая переведёт ваши уведомления в статус авторизованных: При получении уведомления у пользователя появляются две дополнительные кнопки.

Critical Alerts

Эти уведомления полностью игнорируют настройки вашего телефона, выключенный звук или режим «не беспокоить». Последнее изменение добавляет ещё один тип уведомлений — Critical Alerts. Apple рекомендует использовать их в медицинских приложениях (например, у пользователя устройства резко подскочил уровень сахара), а также для обеспечения безопасности пользователей дома или в публичных местах.

Запрос на авторизацию содержит особый знак:

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

Для отправки критических уведомлений придётся пройти процедуру валидации вашего приложения на сайте Apple.

Для использования уведомлений применяем параметр criticalAlert:

UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .criticalAlert])

И формируем содержимое нотификации:

let content = UNMutableNotificationContent()
content.title = "WARNING"
content.body = "Storm alert"
content.categoryIdentifier = "storm-alert"
content.sound = UNNotificationSound.defaultCriticalSound(withAudioVolume: 1.0)

Для Critical Alerts можно указать громкость, с которой нотификация будет срабатывать независимо от настроек пользователя.

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

Обсудить нововведения сможем на MBLT DEV 2018 в Москве 28 сентября. Также можете посмотреть статью от e-Legion по уведомлениям для iOS 10 или запись доклада с WWDC — What’s New in User Notifications.

Хорошего дня и котиков всем ^_^


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Механизм комиссий в Биткоине и зачем дружить с майнерами

В этой статье мы постараемся детально описать основную задачу комиссий в Биткоине, как они работают и на что влияют. Мы объясним причины волатильности комиссий, задержки в подтверждении транзакций и опишем подходы к решению этих проблем. Кроме того, проясним, как именно ...

Бот для Starcraft на Rust

Как много это значит для меня. StarCraft: Brood War. Настолько много, что я засомневался, давать ли ссылку на вики. И для многих из вас. Как и любые нормальные люди, мы решили начать с hello world написания динамической библиотеки под Windows, ...