Ответ
Механизм обработки зависит от состояния приложения (foreground/background или terminated).
Когда приложение открыто (foreground):
- Уведомление доставляется напрямую в код приложения.
- Для UserNotifications framework (iOS 10+) вызывается метод делегата
UNUserNotificationCenterDelegate:func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { // Решение: показать уведомление в интерфейсе или обработать тихо completionHandler([.banner, .sound, .badge]) } - Для устаревшего подхода может вызываться
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)вAppDelegate.
Когда приложение закрыто (terminated) или в фоне (background):
- Система отображает баннер, звук и значок (badge).
- При тапе пользователя на уведомление:
- Если приложение было закрыто, оно запускается, и в
application(_:didFinishLaunchingWithOptions:)доступны данные уведомления вlaunchOptions[.remoteNotification]. - Если приложение было в фоне, оно переходит в foreground, и вызывается
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)илиuserNotificationCenter(_:didReceive:withCompletionHandler:).
- Если приложение было закрыто, оно запускается, и в
Практическое отличие: В foreground вы должны явно решить, как отобразить уведомление (например, через completionHandler). В background/terminated системный баннер показывается автоматически, а ваше приложение получает данные для обработки после взаимодействия пользователя.
Ответ 18+ 🔞
О, слушай, смотри, как эта хуйня работает с пуш-уведомлениями на айфоне. Это же надо, какая разница, где твоё приложение болтается — на переднем плане или в жопе у системы.
Когда приложение у тебя прямо перед рожей (foreground): Вот тут всё просто, как три копейки. Уведомление не лезет в баннер сразу, а прилетает прямиком в код. Ты сам решаешь, что с ним делать — показать или тихо обработать. Если ты юзаешь эту современную хуйню, UserNotifications (iOS 10+), то дергается метод у делегата:
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// Вот тут ты и решаешь: показать интерфейс или молча в сраку закинуть
completionHandler([.banner, .sound, .badge]) // Ну, показываем, допустим
}
А если ты старовер и сидишь на старом AppDelegate, то может вызваться application(_:didReceiveRemoteNotification:fetchCompletionHandler:). В общем, суть одна — ты в курсе и всё контролируешь.
А вот когда приложение закрыто (terminated) или в фоне (background): Тут уже начинается магия, блядь.
- Система сама, без спросу, вываливает тебе баннер, пищит и обновляет бейдж. Твоё приложение в этот момент может вообще спать, как сурок.
- Пользователь тыкает в это уведомление. Вот тут-то и просыпается вся ебля:
- Если приложение было полностью убито, оно запускается заново. Данные от пуша лежат в
launchOptions[.remoteNotification]внутриapplication(_:didFinishLaunchingWithOptions:). Найди их там, епта. - Если приложение просто висело в фоне, оно выпрыгивает на передний план, и вызывается либо старый метод в
AppDelegate, либо новыйuserNotificationCenter(_:didReceive:withCompletionHandler:).
- Если приложение было полностью убито, оно запускается заново. Данные от пуша лежат в
Короче, практическая разница, как небо и земля: Когда на переднем плане — ты царь и бог, сам решаешь, показывать уведомление или нет. А когда в фоне или убито — система сначала сама всё показывает, а твоё приложение получает пинок и данные только после того, как юзер на это дерьмо тапнул. Вот такая, блядь, хитрая жопа с уведомлениями.