← Назад к вопросам

Как реализовать push-уведомление с картинкой?

1.0 Junior🔥 61 комментариев
#Работа с сетью

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализация Push-уведомлений с картинкой в iOS

В iOS push-уведомления с изображениями реализуются через расширения уведомлений (Notification Service Extension). Это отдельный таргет в вашем проекте, который позволяет модифицировать содержимое уведомления до его показа пользователю.

Архитектура решения

  1. Основное приложение - получает стандартное push-уведомление
  2. Notification Service Extension - обрабатывает и обогащает уведомление медиа-контентом
  3. Серверная часть - отправляет уведомление с ссылкой на изображение

Пошаговая реализация

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 Extension
  • image_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-уведомлений

Оптимизации:

  1. Кэширование изображений для повторного использования
  2. Компрессия изображений перед загрузкой
  3. Использование URLSession с правильной конфигурацией
  4. Обработка таймаутов и ошибок сети

Безопасность:

  • Валидация URL перед загрузкой
  • Проверка MIME-типов изображений
  • Ограничение размера загружаемых файлов
  • Использование защищенных соединений (HTTPS)

Альтернативные подходы

  1. Rich Notifications с кастомным UI - создание интерфейса через UNNotificationContentExtension
  2. Локальные уведомления с изображениями - использование локальных файлов
  3. 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-уведомлений с изображениями требует тщательной обработки ошибок и оптимизации загрузки медиа-контента, но значительно улучшает пользовательский опыт.

Как реализовать push-уведомление с картинкой? | PrepBro