Статьи

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

В iOS 10, tvOS 10 и watchOS 3 Apple представляет новую платформу под названием UserNotifications Framework. Этот новый набор API-интерфейсов предоставляет унифицированный объектно-ориентированный способ работы с локальными и удаленными уведомлениями на этих платформах. Это особенно полезно, поскольку по сравнению с существующими API локальные и удаленные уведомления теперь обрабатываются очень схожим образом, и доступ к содержимому уведомлений больше не осуществляется только через словари.

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

Это руководство требует, чтобы вы работали с Xcode 8 с последними SDK для iOS, tvOS и watchOS.

Первым шагом для любого приложения, поддерживающего уведомления, является запрос разрешения от пользователя. Как и в предыдущих версиях iOS, при использовании инфраструктуры UserNotifications, это обычно делается, как только приложение завершает запуск.

Перед использованием любого из API-интерфейсов UserNotifications вам необходимо добавить следующий оператор импорта во все файлы кода Swift, которые обращаются к платформе:

1
import UserNotifications

Затем, чтобы зарегистрировать свое приложение для уведомлений, вам нужно добавить следующий код в приложение вашего AppDelegate application(_:didFinishLaunchingWithOptions:) метод application(_:didFinishLaunchingWithOptions:) :

1
2
3
4
5
6
7
let center = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .badge, .sound]
center.requestAuthorization(options: options) { (granted, error) in
    if granted {
        application.registerForRemoteNotifications()
    }
}

Изначально с помощью этого кода мы получаем ссылку на текущий объект UNUserNotificationCenter . Затем мы настраиваем наши UNAuthorizationOptions с возможностями уведомлений, которые мы хотим, чтобы наше приложение имело. Обратите внимание, что здесь вы можете выбрать любую комбинацию опций, например, просто alert или badge и sound .

Используя оба этих объекта, мы затем запрашиваем авторизацию для нашего приложения для отображения уведомлений, вызывая метод requestAuthorization(options:completionHandler:) в нашем экземпляре UNUserNotificationCenter . Блок обработчика завершения кода имеет два переданных ему параметра:

  • Значение Bool указывающее, была ли предоставлена ​​авторизация пользователем.
  • Необязательный объект Error который будет содержать информацию, если по какой-либо причине система не смогла запросить авторизацию уведомлений для вашего приложения.

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

  • Настройка Push-уведомлений на iOS

Обратите внимание, что при регистрации для удаленных уведомлений будут использоваться те же UIApplication обратного вызова UIApplication что и в предыдущих версиях iOS. В случае успеха application(_:didRegisterForRemoteNotificationsWithDeviceToken:) будет application(_:didRegisterForRemoteNotificationsWithDeviceToken:) , а application(_:didFailToRegisterForRemoteNotificationsWithError:) будет application(_:didFailToRegisterForRemoteNotificationsWithError:) .

В этом разделе руководства мы полностью сосредоточимся на планировании локальных уведомлений с использованием инфраструктуры UserNotifications. Отправка удаленных push-уведомлений не изменилась благодаря внедрению этого нового фреймворка.

Локальное уведомление перед планированием представляется экземпляром класса UNNotificationRequest . Объекты этого типа состоят из следующих компонентов:

  • Идентификатор: уникальная String которая позволяет отличать отдельные уведомления друг от друга.
  • Содержимое: объект UNNotificationContent который содержит всю информацию, необходимую для отображения вашего уведомления, включая заголовок, подзаголовок и номер значка приложения.
  • Триггер: объект UNNotificationTrigger который используется системой, чтобы определить, когда ваше уведомление должно быть «отправлено» в ваше приложение.

Для начала мы рассмотрим различные типы триггеров, которые вы можете настроить для локальных уведомлений. Класс UNNotificationTrigger является абстрактным классом, что означает, что вы никогда не должны создавать его экземпляры напрямую. Вместо этого вы будете использовать доступные подклассы. В настоящее время платформа UserNotifications предоставляет три для вас:

  • UNTimeIntervalNotificationTrigger , который позволяет отправлять уведомление через определенный промежуток времени после его планирования.
  • UNCalendarNotificationTrigger , который позволяет отправлять уведомление в определенную дату и время, независимо от того, когда оно было запланировано.
  • UNLocationNotificationTrigger , который позволяет отправлять уведомление, когда пользователь входит или покидает указанный географический регион.

Следующий код показывает вам, как вы можете сделать триггер каждого типа:

01
02
03
04
05
06
07
08
09
10
11
let timeTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 60.0 * 60.0, repeats: false)
 
var date = DateComponents()
date.hour = 22
let calendarTrigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
 
let center = CLLocationCoordinate2D(latitude: 40.0, longitude: 120.0)
let region = CLCircularRegion(center: center, radius: 500.0, identifier: «Location»)
region.notifyOnEntry = true;
region.notifyOnExit = false;
let locationTrigger = UNLocationNotificationTrigger(region: region, repeats: false)

С помощью приведенного выше кода были созданы следующие условия запуска:

  • timeTrigger сработает через час после запланированного уведомления. Параметр timeInterval передаваемый в инициализатор UNTimeIntervalNotificationTrigger измеряется в секундах.
  • calendarTrigger будет многократно срабатывать каждый день в 22:00. Точную дату и время срабатывания триггера можно легко изменить, изменив другие свойства объекта DateComponents вы передаете в инициализатор UNCalendarNotificationTrigger .
  • locationTrigger срабатывает, когда пользователь находится в пределах 500 метров от назначенной координаты, в этом случае 40 ° N 120 ° E. Как видно из кода, этот тип триггера может использоваться для любой координаты и / или размера области, а также может инициировать уведомление как при входе, так и при выходе из региона.

Далее нам нужно создать контент для уведомления. Это делается путем создания экземпляра класса UNMutableNotificationContent . Этот класс должен использоваться, так как обычный класс UNNotificationContent имеет доступ только для чтения для различных свойств содержимого уведомлений.

Следующий код показывает, как можно создать контент для базового уведомления:

1
2
3
4
5
6
let content = UNMutableNotificationContent()
content.title = «Notification Title»
content.subtitle = «Notification Subtitle»
content.body = «Some notification body information to be displayed.»
content.badge = 1
content.sound = UNNotificationSound.default()

Если вы хотите получить полный список доступных вам свойств, взгляните на UNMutableNotificationContent класс UNMutableNotificationContent .

Наконец, теперь нам просто нужно создать объект UNNotificationRequest и запланировать его. Это можно сделать с помощью следующего кода:

1
2
3
4
5
6
7
8
let request = UNNotificationRequest(identifier: «LocalNotification», content: content, trigger: timeTrigger)
UNUserNotificationCenter.current().add(request) { error in
    if let error = error {
        // Do something with error
    } else {
        // Request was added successfully
    }
}

Изначально с помощью этого кода мы создаем объект запроса, передавая идентификатор, объект содержимого и триггер в инициализатор. Затем мы вызываем метод add(_:completionHandler:) для текущего объекта UNUserNotificationCenter и используем обработчик завершения для выполнения логики на основе того, правильно ли было запланировано уведомление.

При использовании инфраструктуры UserNotifications обработка входящих уведомлений обрабатывается объектом, который вы определяете в соответствии с протоколом UNUserNotificationCenterDelegate . Этот объект может быть чем угодно и не обязательно должен быть делегатом приложения, как в предыдущих версиях iOS.

Однако важно отметить, что вы должны установить свой делегат до того, как ваше приложение будет полностью запущено. Для приложения iOS это означает, что вы должны назначить свой делегат либо внутри application(_:willFinishLaunchingWithOptions:) либо в application(_:didFinishLaunchingWithOptions:) метода вашего делегата приложения. Установка делегата для пользовательских уведомлений выполняется очень легко с помощью следующего кода:

1
UNUserNotificationCenter.current().delegate = delegateObject

Теперь с вашим установленным делегатом, когда приложение получает уведомление, есть только два метода, о которых вам нужно беспокоиться. Оба метода передают объект UNNotification , который представляет полученное уведомление. Этот объект содержит свойство date , которое точно сообщает, когда было доставлено уведомление, и свойство request , которое является экземпляром класса UNNotificationRequest упомянутого ранее. Из этого объекта запроса вы можете получить доступ к содержанию уведомления, а также (при необходимости) к триггеру для уведомления. Этот триггерный объект будет экземпляром одного из упомянутых ранее подклассов UNNotificationTrigger или, в случае push-уведомлений, экземпляром класса UNPushNotificationTrigger .

Первым методом, определенным протоколом UNUserNotificationCenterDelegate , является метод userNotificationCenter(_:willPresent:withCompletionHandler:) . Это вызывается только тогда, когда ваше приложение работает на переднем плане и получает уведомление. Отсюда вы можете получить доступ к содержанию уведомления и при необходимости отобразить свой собственный интерфейс в приложении. В качестве альтернативы вы можете указать системе представить уведомление с различными вариантами, как обычно, если ваше приложение не работает. Доступные варианты:

  • Оповещение для отображения сгенерированного системой интерфейса для уведомления
  • Звук для воспроизведения звука, связанного с уведомлением
  • Значок для редактирования значка вашего приложения на домашнем экране пользователя

В следующем коде показан пример реализации метода userNotificationCenter(_:willPresent:withCompletionHandler:) :

1
2
3
4
5
6
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    let content = notification.request.content
    // Process notification content
     
    completionHandler([.alert, .sound]) // Display notification as regular alert and play sound
}

Другой метод, определенный в протоколе UNUserNotificationCenterDelegate , — это userNotificationCenter(_:didReceive:withCompletionHandler:) . Этот метод вызывается, когда пользователь каким-либо образом взаимодействует с уведомлением для вашего приложения, включая его закрытие или открытие из него приложения.

Вместо объекта UNNotification этот метод имеет объект UNNotificationResponse переданный в качестве параметра. Этот объект содержит объект UNNotification представляющий доставленное уведомление. Он также включает свойство actionIdentifier для определения того, как пользователь взаимодействовал с уведомлением. В случае отклонения уведомления или открытия вашего приложения платформа UserNotifications предоставляет постоянные идентификаторы действий для сравнения.

В следующем коде показан пример реализации метода userNotificationCenter(_:didReceive:withCompletionHandler:) :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let actionIdentifier = response.actionIdentifier
     
    switch actionIdentifier {
    case UNNotificationDismissActionIdentifier: // Notification was dismissed by user
        // Do something
        completionHandler()
    case UNNotificationDefaultActionIdentifier: // App was opened from notification
        // Do something
        completionHandler()
    default:
        completionHandler()
    }
}

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

Иногда пользователь вашего приложения может получать несколько уведомлений, когда ваше приложение не запущено. Они также могут открывать ваше приложение прямо с главного экрана, а не через уведомление. В любом из этих случаев не будет вызван ни один из UNUserNotificationCenterDelegate протокола UNUserNotificationCenterDelegate . При работе с локальными уведомлениями иногда может потребоваться удалить запланированное уведомление до его отображения пользователю.

Вследствие этого платформа UserNotifications предоставляет следующие методы для текущего экземпляра UNUserNotificationCenter для работы с ожидающими локальными уведомлениями и доставленными уведомлениями, которые еще не были обработаны:

  • getPendingNotificationRequests(completionHandler:) предоставляет вам массив объектов UNNotificationRequest в обработчике завершения. Этот массив будет содержать все локальные уведомления, которые вы запланировали, которые еще не были запущены.
  • removePendingNotificationRequests(withIdentifiers:) удаляет все запланированные локальные уведомления с идентификаторами, содержащимися в массиве String вы передаете в качестве параметра.
  • removeAllPendingNotificationRequests удаляет все запланированные локальные уведомления для вашего приложения.
  • getDeliveredNotifications(completionHandler:) предоставляет вам массив объектов UNNotification в обработчике завершения. Этот массив будет содержать все уведомления, доставленные для вашего приложения, которые все еще видны в Центре уведомлений пользователя.
  • removeDeliveredNotifications(withIdentifiers:) удаляет все доставленные уведомления с идентификаторами, содержащимися в массиве String вы передаете из Центра уведомлений пользователя.
  • removeAllDeliveredNotifications удаляет все доставленные уведомления для вашего приложения.

Платформа UserNotifications также позволяет вашему приложению легко использовать преимущества пользовательских категорий уведомлений и действий, представленных в iOS 8.

Во-первых, вам нужно определить настраиваемые действия и категории, которые поддерживает ваше приложение, используя UNNotificationAction и UNNotificationCategory соответственно. Для действий, в которых вы хотите, чтобы пользователь мог вводить текст, вы можете использовать класс UNTextInputNotificationAction , который является подклассом UNNotificationAction . Как только ваши действия и категории определены, вам просто нужно вызвать метод setNotificationCategories(_:) для текущего экземпляра UNUserNotificationCenter . В следующем коде показано, как можно легко зарегистрировать ответ и удалить действия для уведомления о категории сообщений в своем собственном приложении:

1
2
3
4
let replyAction = UNTextInputNotificationAction(identifier: «com.usernotificationstutorial.reply», title: «Reply», options: [], textInputButtonTitle: «Send», textInputPlaceholder: «Type your message»)
let deleteAction = UNNotificationAction(identifier: «com.usernotificationstutorial.delete», title: «Delete», options: [.authenticationRequired, .destructive])
let category = UNNotificationCategory(identifier: «com.usernotificationstutorial.message», actions: [replyAction, deleteAction], intentIdentifiers: [], options: [])
center.setNotificationCategories([category])

Затем, когда пользователь использует одно из ваших пользовательских действий по уведомлению, userNotificationCenter(_:didReceive:withCompletionHandler:) тот же userNotificationCenter(_:didReceive:withCompletionHandler:) который мы рассмотрели ранее. В этом случае идентификатор действия UNNotificationResponse объекта UNNotificationResponse будет таким же, как тот, который вы определили для своего настраиваемого действия. Также важно отметить, что, если пользователь взаимодействовал с действием уведомления о вводе текста, объект ответа, передаваемый в этот метод, будет иметь тип UNTextInputNotificationResponse .

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let actionIdentifier = response.actionIdentifier
    let content = response.notification.request.content
     
    switch actionIdentifier {
    case UNNotificationDismissActionIdentifier: // Notification was dismissed by user
        // Do something
        completionHandler()
    case UNNotificationDefaultActionIdentifier: // App was opened from notification
        // Do something
        completionHandler()
    case «com.usernotificationstutorial.reply»:
        if let textResponse = response as?
            let reply = textResponse.userText
            // Send reply message
            completionHandler()
        }
    case «com.usernotificationstutorial.delete»:
        // Delete message
        completionHandler()
    default:
        completionHandler()
    }
}

Кроме того, если вы хотите воспользоваться настраиваемыми действиями для локальных уведомлений, вы можете просто установить свойство categoryIdentifier для вашего объекта UNMutableNotificationContent при создании уведомления.

Новая платформа UserNotifications предоставляет полностью функциональные и простые в использовании объектно-ориентированные API-интерфейсы для работы с локальными и удаленными уведомлениями на iOS, watchOS и tvOS. Это позволяет очень легко планировать локальные уведомления для различных сценариев, а также значительно упрощает весь процесс обработки входящих уведомлений и пользовательских действий.

Как всегда, пожалуйста, оставляйте свои комментарии и отзывы в комментариях ниже. И ознакомьтесь с некоторыми другими нашими статьями и учебными пособиями о новых функциях в iOS 10 и watchOS 3!

  • IOS
    WWDC 2016 Последствия
  • iOS SDK
    Создайте приложение iMessage в iOS 10
  • watchOS
    Что нового в watchOS 3: фоновые задачи