Notification Extension é um mecanismo do iOS que permite modificar o conteúdo e a aparência de notificações push antes de serem exibidas ao usuário. As extensões operam no lado do sistema operacional em um processo separado: UNNotificationServiceExtension processa o conteúdo recebido, enquanto UNNotificationContentExtension gerencia a interface. De acordo com Apple Developer Documentation, 2026, a Service Extension tem até 30 segundos para executar tarefas antes da notificação ser exibida. Essa limitação é crítica ao baixar anexos ou descriptografar dados.
Pontos principais
Notification Extension é um componente de software do iOS que estende o comportamento padrão das notificações push adicionando a capacidade de modificar conteúdo e personalizar a interface. Diferente das notificações comuns que o sistema exibe em formato padrão, as extensões permitem que o desenvolvedor influencie o conteúdo antes da exibição e crie uma interface de usuário única.
A Apple fornece dois tipos de Notification Extension para diferentes propósitos: UNNotificationServiceExtension lida com o processamento do payload recebido, enquanto UNNotificationContentExtension gerencia a exibição. A Service Extension é executada antes da notificação ser mostrada e tem tempo de execução limitado — até 30 segundos de acordo com a Apple Developer Documentation. A Content Extension é ativada após o usuário interagir com a notificação e exibe uma visualização personalizada.
Uma notificação push padrão do iOS é exibida automaticamente pelo sistema com base nos campos alert, title e subtitle do payload JSON. Notification Extension intercepta o controle: a Service Extension recebe o payload bruto, modifica-o e o passa para o sistema exibir. A Content Extension substitui o banner padrão por uma interface personalizada com quaisquer elementos de controle.
Quando o dispositivo recebe uma notificação push com a chave mutable-content: 1, o sistema inicia a Service Extension em um processo separado. O processo da extensão é isolado do aplicativo principal e tem sua própria sandbox com limite de memória de 50 MB. Após concluir o processamento, a extensão chama o completion handler, passando o UNNotificationContent modificado ao sistema para exibição.
UNNotificationServiceExtension é a principal ferramenta para modificar programaticamente notificações push antes de serem exibidas ao usuário. A extensão é ativada automaticamente ao receber uma notificação cujo payload tenha a flag mutable-content: 1 configurada. Em 30 segundos, a extensão pode baixar um anexo de mídia, alterar texto, descriptografar dados criptografados ou enriquecer o conteúdo.
A extensão implementa dois métodos-chave do protocolo UNNotificationServiceExtension. O método didReceive recebe a solicitação recebida com o UNNotificationRequest bruto e permite modificação através do completion handler com um novo UNNotificationContent. O método serviceExtensionTimeWillExpire é chamado pelo sistema um segundo antes do tempo limite — nele você deve completar o processamento e passar o resultado atual (possivelmente parcial).
Considere um cenário onde o servidor envia um push com uma URL de imagem em um campo personalizado. A Service Extension baixa esta imagem pela rede, cria um UNNotificationAttachment e o adiciona ao conteúdo. UNNotificationAttachment aceita um arquivo local de imagem, vídeo ou áudio e o copia automaticamente para a sandbox da extensão. Após criar o anexo, a extensão passa o conteúdo atualizado ao sistema.
class NotificationService: UNNotificationServiceExtension {
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler:
@escaping (UNNotificationContent) -> Void) {
let userInfo = request.content.userInfo
guard let imageURL = URL(string: userInfo["image-url"] as! String)
else { contentHandler(request.content); return }
let attachment = try! UNNotificationAttachment(
identifier: "image", url: imageURL,
options: [UNNotificationAttachmentOptionsTypeHintKey: "jpg"])
let modifiedContent = request.content.mutableCopy()
as! UNMutableNotificationContent
modifiedContent.attachments = [attachment]
contentHandler(modifiedContent)
}
override func serviceExtensionTimeWillExpire() {
contentHandler?(bestAttemptContent ?? request.content)
}
}
Quando notificações com os mesmos anexos são enviadas com frequência, é recomendado armazenar em cache os arquivos baixados no dispositivo. FileManager fornece acesso ao diretório de cache da extensão, que persiste entre execuções. Isso reduz o tempo de processamento de notificações subsequentes e diminui a carga de rede. De acordo com a Apple, o cache pode reduzir o tempo de processamento para 2–5 segundos em vez de um download completo.
UNNotificationContentExtension permite substituir o banner padrão de notificação por uma interface personalizada criada no Interface Builder ou SwiftUI. A extensão é ativada quando o usuário realiza uma ação na notificação: tocar, deslizar para baixo ou 3D Touch. A Content Extension recebe o conteúdo já processado pela Service Extension e o exibe em uma visualização personalizada.
Cada Content Extension é vinculada a uma ou mais categorias de notificação através do Info.plist. A categoria é definida no servidor pelo campo category no payload APNS. O sistema seleciona automaticamente a extensão apropriada com base na categoria da notificação recebida. A interface é construída via storyboard usando componentes UIKit padrão ou SwiftUI View.
Content Extension suporta botões personalizados e manipuladores de toque definidos em UNNotificationAction. UNNotificationAction é criado na etapa de registro da categoria e pode suportar entrada de texto via UNTextInputNotificationAction. Quando o usuário pressiona um botão, a extensão recebe o callback didReceive com o identificador da ação e pode executar a lógica correspondente — abrir uma URL, enviar uma solicitação ao servidor ou atualizar a interface.
A Content Extension é executada em um processo isolado com seu próprio ciclo de execução e um limite de memória de aproximadamente 50 MB. O desempenho da extensão é crítico porque o watchdog do sistema encerra o processo quando os limites são excedidos. É recomendado evitar cálculos pesados, carregamento de imagens grandes e solicitações de rede prolongadas dentro da Content Extension.
UNNotificationAttachment é um objeto que adiciona um arquivo de mídia a uma notificação push: imagem, vídeo, áudio ou GIF. O anexo é criado a partir de uma URL de arquivo local que deve estar na sandbox da extensão. O tamanho máximo do anexo não deve exceder 10 MB, caso contrário o sistema rejeitará o anexo ao criá-lo.
A Apple suporta um conjunto limitado de formatos para anexos de mídia. Imagens — JPEG, PNG, GIF (incluindo animados), TIFF. Vídeo — MPEG, MP4, MOV com duração máxima de 30 segundos. Áudio — MP3, AAC, WAV, CAF. Para cada formato, você pode especificar o tipo através de UNNotificationAttachmentOptionsTypeHintKey, o que ajuda o sistema a processar o arquivo corretamente.
Como o payload push contém apenas uma URL, não o arquivo em si, o download do anexo deve ser feito dentro da Service Extension. O tempo máximo de download é limitado a 30 segundos, portanto é recomendado usar URLSession com configurações mínimas e desabilitar o download em sinal fraco. Se o anexo não carregar a tempo, a notificação é exibida sem mídia — este é o comportamento padrão do sistema.
Vamos percorrer um exemplo completo de Notification Extension que baixa uma imagem, salva e a adiciona à notificação. NotificationService herda de UNNotificationServiceExtension e sobrescreve o método didReceive. O exemplo mostra o tratamento de campos opcionais, criação do anexo e chamada do completion handler com conteúdo modificado.
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
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 attachmentURLString =
bestAttemptContent?.userInfo["attachment-url"] as? String,
let url = URL(string: attachmentURLString)
else {
contentHandler(request.content)
return
}
URLSession.shared.downloadTask(with: url) {
[weak self] localURL, _, error in
guard let localURL = localURL, error == nil
else {
contentHandler(request.content)
return
}
let attachment = try! UNNotificationAttachment(
identifier: "media", url: localURL)
self?.bestAttemptContent?.attachments = [attachment]
contentHandler(self?.bestAttemptContent
?? request.content)
}.resume()
}
override func serviceExtensionTimeWillExpire() {
if let content = bestAttemptContent {
contentHandler?(content)
}
}
}
Para a extensão funcionar corretamente, é necessário registrar as categorias de notificação no Info.plist. A chave NSExtensionPointIdentifier é definida como com.apple.usernotifications.service para Service Extension ou com.apple.usernotifications.content para Content Extension. As categorias são definidas no AppDelegate ao iniciar o aplicativo através de UNUserNotificationCenter, e a extensão só é ativada para notificações com uma categoria correspondente no payload.
Perguntas frequentes
Service Extension modifica o conteúdo antes da notificação ser exibida — adiciona mídia, altera texto, descriptografa dados. Content Extension substitui a interface da notificação por uma personalizada após a interação do usuário. Service Extension funciona antes da exibição, Content Extension depois.
O sistema aloca 30 segundos para execução de código no didReceive. Se o processamento não for concluído dentro deste tempo, serviceExtensionTimeWillExpire é chamado, onde você deve passar o resultado atual. Recomenda-se ficar dentro de 10–15 segundos considerando downloads de anexos.
Sim, SwiftUI é suportado na Content Extension a partir do iOS 16. A View é encapsulada em um UIHostingController e adicionada ao storyboard. No entanto, devido aos limites de memória, recomenda-se usar SwiftUI apenas para interfaces simples com número mínimo de elementos.
Em caso de erro de download ou tempo limite, simplesmente chame o completion handler com o conteúdo original sem anexo. O sistema exibirá a notificação no formato padrão sem mídia. Registre erros via OSLog para diagnóstico, mas não bloqueie a exibição da notificação.
A extensão é executada em um processo isolado com um limite de aproximadamente 50 MB. Quando excedido, o sistema encerra o processo via watchdog. Evite carregar arquivos grandes, armazenar imagens em memória e vazamentos ao trabalhar com URLSession.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também