Ведение журнала из расширения службы уведомлений

Итак, сейчас я делаю это:

override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    logger = AnalyticsManager.shared
    self.contentHandler = contentHandler
    bestAttemptContent = (request.content.mutableCopy() as! UNMutableNotificationContent)
    if let notificationContent = bestAttemptContent {
        extensionHandler = ServiceExtensionHandler(notificationContent: notificationContent, logger: AnalyticsManager.shared)
        extensionHandler?.handleNotificationRequest { modifiedNotificationContent in
            guard let modifiedNotificationContent = modifiedNotificationContent else {
                contentHandler(notificationContent)
                return
            }
            contentHandler(modifiedNotificationContent)
        }
    } else {
        contentHandler(request.content)
        return
    }
}

В моем ServiceExtensionHandlerесли загрузка изображения завершится успешно, я верну измененное уведомление. Все идет нормально.

Но после успешной загрузки изображения я хочу зарегистрировать событие. Проблема в том, если я вернуcontentHandler тогда ОС убьет расширение, и я не успею заполнить журнал.

Вскоре после того, как расширение приложения выполнит свою задачу (или запустит фоновый сеанс для ее выполнения), система завершит работу расширения.

Документы: жизненный цикл расширения приложения

На данный момент он работает, но этот дополнительный сетевой вызов не гарантирован.

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

Кто-нибудь придумал какие-либо решения для этого?

1 ответ

Решение

Вы на правильном пути.

Вы должны вернуть contentHandlerв конечном итоге из обратного вызова, который является производным от обратного вызова сети ведения журнала. С небольшими изменениями:

Для сетевого вызова журнала установите его URLSessionConfiguration s timeoutIntervalForRequest на что-то менее 5 секунд. Таким образом, вам не придется долго ждать его завершения.

Это псевдокод, но для объекта, который ведет журнал, сделайте что-то вроде:

if let imageData = data {
    self?.log("downloadSuccess") {
        completionHandler(imageData, nil)
   }
}

Он либо преуспевает / терпит неудачу менее чем за 5 секунд, либо, если время ожидания истекает, это не займет больше 5 секунд.