← Назад к вопросам
Как реализовать push-уведомление с картинкой?
1.0 Junior🔥 61 комментариев
#Работа с сетью
Комментарии (1)
🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Реализация Push-уведомлений с картинкой в iOS
В iOS push-уведомления с изображениями реализуются через расширения уведомлений (Notification Service Extension). Это отдельный таргет в вашем проекте, который позволяет модифицировать содержимое уведомления до его показа пользователю.
Архитектура решения
- Основное приложение - получает стандартное push-уведомление
- Notification Service Extension - обрабатывает и обогащает уведомление медиа-контентом
- Серверная часть - отправляет уведомление с ссылкой на изображение
Пошаговая реализация
1. Добавление Notification Service Extension
В Xcode: File → New → Target → Notification Service Extension
import UserNotifications
import UIKit
class NotificationService: UNNotificationServiceExtension {
private var contentHandler: ((UNNotificationContent) -> Void)?
private var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
guard let bestAttemptContent = bestAttemptContent else {
contentHandler(request.content)
return
}
// Извлекаем URL изображения из payload
guard let imageUrlString = bestAttemptContent.userInfo["image_url"] as? String,
let imageUrl = URL(string: imageUrlString) else {
contentHandler(bestAttemptContent)
return
}
// Загружаем изображение
downloadAndAttachImage(url: imageUrl, to: bestAttemptContent)
}
private func downloadAndAttachImage(url: URL, to content: UNMutableNotificationContent) {
URLSession.shared.downloadTask(with: url) { (location, response, error) in
guard let location = location, error == nil else {
self.contentHandler?(content)
return
}
// Перемещаем файл в temporary directory
let tempDirectory = FileManager.default.temporaryDirectory
let tempFileUrl = tempDirectory.appendingPathComponent(url.lastPathComponent)
try? FileManager.default.moveItem(at: location, to: tempFileUrl)
// Создаем attachment
if let attachment = try? UNNotificationAttachment(identifier: "image",
url: tempFileUrl,
options: nil) {
content.attachments = [attachment]
}
self.contentHandler?(content)
}.resume()
}
override func serviceExtensionTimeWillExpire() {
// Вызывается перед завершением времени на обработку
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
2. Настройка payload на сервере
Сервер должен отправлять уведомление со специальной структурой:
{
"aps": {
"alert": {
"title": "Новое уведомление",
"body": "Посмотрите это изображение!"
},
"mutable-content": 1,
"sound": "default"
},
"image_url": "https://example.com/image.jpg"
}
Ключевые моменты payload:
"mutable-content": 1- обязательный флаг для активации Service Extensionimage_url- кастомное поле с URL изображения- Максимальный размер изображения: до 10 МБ
- Поддерживаемые форматы: JPEG, PNG, GIF, MPEG
3. Обработка в основном приложении
import UserNotifications
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Запрос разрешения на уведомления
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
DispatchQueue.main.async {
if granted {
application.registerForRemoteNotifications()
}
}
}
UNUserNotificationCenter.current().delegate = self
return true
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// Обработка уведомления, когда приложение активно
completionHandler([.banner, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
// Обработка нажатия на уведомление
let userInfo = response.notification.request.content.userInfo
if let imageUrl = userInfo["image_url"] as? String {
// Открываем изображение в приложении
handleImageNotification(url: imageUrl)
}
completionHandler()
}
}
Важные нюансы реализации
Ограничения и требования:
- Service Extension имеет ограниченное время выполнения (примерно 30 секунд)
- Максимальный размер изображения: 10 МБ
- Изображение должно быть доступно по HTTPS
- Поддерживаются локальные файлы через
file://URL - Расширение работает только для удаленных push-уведомлений
Оптимизации:
- Кэширование изображений для повторного использования
- Компрессия изображений перед загрузкой
- Использование
URLSessionс правильной конфигурацией - Обработка таймаутов и ошибок сети
Безопасность:
- Валидация URL перед загрузкой
- Проверка MIME-типов изображений
- Ограничение размера загружаемых файлов
- Использование защищенных соединений (HTTPS)
Альтернативные подходы
- Rich Notifications с кастомным UI - создание интерфейса через
UNNotificationContentExtension - Локальные уведомления с изображениями - использование локальных файлов
- Third-party библиотеки - Firebase, OneSignal и другие предлагают свои решения
Тестирование
Для тестирования можно использовать:
- Консоль разработчика Apple
- Команду
curlс APNs сертификатами - Специализированные сервисы типа Pusher или Postman с APNs плагином
curl -v \
--header "apns-topic: com.your.app.bundle" \
--header "apns-push-type: alert" \
--header "authorization: bearer YOUR_TOKEN" \
--data '{"aps":{"alert":"Test","mutable-content":1},"image_url":"https://picsum.photos/400/300"}' \
--http2 https://api.sandbox.push.apple.com/3/device/DEVICE_TOKEN
Реализация push-уведомлений с изображениями требует тщательной обработки ошибок и оптимизации загрузки медиа-контента, но значительно улучшает пользовательский опыт.