Ответ
Обработка зависит от состояния приложения в момент доставки уведомления (APNs payload).
1. Приложение запущено и активно (Foreground):
- Уведомление не показывается в системном центре уведомлений по умолчанию.
- Вызывается метод
userNotificationCenter(_:willPresent:withCompletionHandler:)делегатаUNUserNotificationCenter. - Решение на стороне приложения: Вы можете решить, показать ли алерт, воспроизвести звук или обработать уведомление тихо.
2. Приложение запущено в фоне (Background) или свернуто (Suspended):
- С payload
content-available: 1(Silent Push):- Система пробуждает приложение в фоне.
- Вызывается
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)вAppDelegate. - У вас есть ~30 секунд на выполнение фоновой задачи (обновление данных, загрузка контента).
- Вы обязаны вызвать
completionHandlerс результатом (.newData,.noData,.failed).
- Без
content-availableили с ним, но сalert,sound,badge:- Система показывает уведомление пользователю.
- При тапе по уведомлению приложение переходит в активное состояние, и вызывается
userNotificationCenter(_:didReceive:withCompletionHandler:).
3. Приложение не запущено (Not Running / Terminated):
- Система показывает уведомление.
- При тапе по уведомлению приложение запускается заново.
- Полезная нагрузка (payload) уведомления передается в параметре
launchOptionsметодаapplication(_:didFinishLaunchingWithOptions:)по ключу.remoteNotification.
Пример обработки Silent Push в фоне:
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
// 1. Проверяем флаг content-available
guard let aps = userInfo["aps"] as? [String: Any],
aps["content-available"] as? Int == 1 else {
// Это не silent push, возможно, просто показ уведомления
completionHandler(.noData)
return
}
// 2. Выполняем фоновую задачу (например, загрузку данных)
fetchNewData { success in
// 3. Обязательно сообщаем системе о результате
completionHandler(success ? .newData : .failed)
}
}