Live Activity é um widget dinâmico no ecrã de bloqueio do iPhone e no Dynamic Island que exibe informações em tempo real: estado de entrega, resultados desportivos, temporizadores e reprodução de música. É implementado através do ActivityKit (Swift, iOS 16.1+) juntamente com o WidgetKit. A Live Activity atualiza-se localmente ou através de notificações push, suporta vários estados e é terminada pelo sistema após o fim do evento. Saiba mais em ActivityKit Documentation.
Pontos principais
Live Activity é uma extensão do WidgetKit que exibe conteúdo dinâmico no ecrã de bloqueio do iPhone e no Dynamic Island. Ao contrário de um widget estático que atualiza num temporizador do sistema, a Live Activity é iniciada pela app e vive por um tempo limitado — até 8 horas para uma Activity ativa e até 4 horas após a conclusão. O utilizador vê dados atualizados sem desbloquear o dispositivo: estado da encomenda, distância ao destino num táxi, resultados de um jogo ou progresso do treino.
ActivityKit é um framework para trabalhar com Live Activities, apresentado no iOS 16.1. Fornece uma API para solicitar, atualizar e terminar Activities. Uma Activity é um objeto com conteúdo e estado. O conteúdo (ActivityContent) define dados estáticos, enquanto o estado (ActivityState) define dados dinâmicos que mudam ao longo do tempo. O próprio sistema decide quando renderizar o novo estado — isto poupa bateria e garante animações suaves.
Cada Live Activity é identificada exclusivamente por um ActivityID e está ligada a um processo — a app que a criou. O sistema pode terminar a Activity quando a memória está baixa ou a bateria está fraca. O programador recebe uma notificação de término forçado através do delegado do ActivityKit e pode guardar o último estado para restauração.
A arquitetura da Live Activity é construída em dois frameworks: o WidgetKit é responsável pela renderização das vistas SwiftUI, o ActivityKit gere o ciclo de vida da Activity. O programador cria um WidgetBundle com suporte para LiveActivityConfiguration. Cada configuração define o tipo de dados (Attributes e State) e uma vista SwiftUI que o sistema renderiza no ecrã de bloqueio e Dynamic Island. Os dados são passados através de ActivityAttributes — uma struct com campos let para conteúdo e campos var para estado.
| Componente | Propósito | API |
|---|---|---|
| Attributes | Dados estáticos de toda a Activity | let name: String, let icon: String |
| ContentState | Estado dinâmico, modificável na atualização | var progress: Double, var status: Status |
| Activity | Objeto de solicitação e gestão da Activity | Activity.request(attributes:content:) |
| PushToken | Token para atualizações push do servidor | activity.pushToken publisher |
| ActivityUI | Vista SwiftUI para ecrã de bloqueio e Dynamic Island | LockScreenView, ExpandedView, CompactView |
Ciclo de vida da Activity inclui três fases: ativa (o sistema exibe e atualiza), final (a atividade terminou mas a UI ainda está visível por 4 horas), removida (o sistema remove a UI). A app pode terminar a Activity a qualquer momento. O sistema também termina Activities à força — por exemplo, ao reiniciar o dispositivo ou quando o limite de 8 horas expira.
import ActivityKit
struct DeliveryAttributes: ActivityAttributes {
public struct ContentState: Codable & Hashable {
var status: DeliveryStatus
var estimatedMinutes: Int
}
var orderNumber: String
var restaurantName: String
}
WidgetBundle regista a Live Activity através da macro @main: o widget devolve uma lista de configurações incluindo LiveActivityConfiguration. Com base nesta configuração, o sistema sabe que tipos de dados esperar e como renderizar a UI em diferentes estados — compacto, mínimo e expandido para Dynamic Island.
Criar uma Activity começa com um pedido ao ActivityKit. A app chama Activity.request(attributes:content:pushType:) com dados iniciais. O sistema verifica se o Dynamic Island está disponível no dispositivo e devolve um objeto Activity. O pedido pode falhar se o limite de Activities ativas for excedido — normalmente não mais de 5 simultaneamente. Após um pedido bem-sucedido, o sistema exibe o widget no ecrã de bloqueio e, se disponível, no Dynamic Island.
let attributes = DeliveryAttributes(
orderNumber: "A-1234",
restaurantName: "Pizza House"
)
let initialState = DeliveryAttributes.ContentState(
status: DeliveryStatus.preparing,
estimatedMinutes: 30
)
do {
let activity = try await Activity<DeliveryAttributes>.request(
attributes: attributes,
content: ActivityContent(state: initialState, staleDate: nil),
pushType: .token
)
print("Activity started: \(activity.id)")
} catch {
print("Failed: \(error)")
}
A vista SwiftUI para Live Activity utiliza as estruturas LockScreenView, ExpandedView e CompactView do WidgetKit. A vista recebe o contexto (ActivityViewContext) com os atributos e estado atuais. A atualização da vista ocorre automaticamente quando um novo estado chega do sistema. A Live Activity suporta apenas um conjunto limitado de componentes SwiftUI — Text, Image, HStack, VStack e alguns modificadores.
Cada vista de Live Activity deve ser leve e rápida — o sistema recusa-se a renderizar vistas pesadas. O limite de tempo de renderização é de 30 ms por frame. As animações estão limitadas a transições do sistema entre estados — animações personalizadas não estão disponíveis na Live Activity. A renderização é realizada num processo de fundo do WidgetKit com prioridade de resposta do ecrã de bloqueio.
Atualização local — a app atualiza o estado da Activity chamando activity.update(using:). O método aceita um novo ContentState e um AlertConfiguration opcional para mostrar uma notificação na atualização. As atualizações locais são rápidas — o sistema redesenha a vista no próximo ciclo de renderização, normalmente dentro de 1–2 segundos. Para atualizações frequentes (temporizador, cronómetro) use o modo local — é mais fiável e rápido que push.
let updatedState = DeliveryAttributes.ContentState(
status: DeliveryStatus.outForDelivery,
estimatedMinutes: 10
)
await activity.update(
ActivityContent<DeliveryAttributes.ContentState>(
state: updatedState,
staleDate: Date().addingTimeInterval(60)
),
alertConfiguration: AlertConfiguration(
title: "Order out for delivery",
body: "Arriving in 10 min"
)
)
Atualizações push — o servidor envia uma notificação push do ActivityKit com o novo estado em formato JSON. Para isso, a app recebe um pushToken do publicador activity.pushToken e passa-o ao servidor. O servidor envia um pedido POST aos APNs com um payload contendo o novo ContentState. O sistema recebe o push, descodifica o estado e atualiza a Live Activity sem envolvimento da app — isto permite atualizar a Activity mesmo quando a app está fechada.
As atualizações push são mais eficientes do que as locais para atualizações pouco frequentes (estado de entrega a cada 5–10 minutos) — a app não precisa de manter uma ligação de rede. Para atualizações frequentes a cada 1–2 segundos use o método local. O payload do servidor inclui apenas os campos mutáveis do ContentState — os dados estáticos dos Attributes são enviados apenas ao criar a Activity.
Dynamic Island é uma área de hardware e software no iPhone 14 Pro, 15 Pro e posteriores que se adapta ao conteúdo da Live Activity. O sistema exibe automaticamente a Activity em três modos: compacto (ícone + texto curto à esquerdo do recorte), mínimo (apenas ícone) e expandido (retângulo de 300pt com informações). O programador não controla estes modos diretamente — o sistema seleciona o modo com base na prioridade e espaço disponível.
struct DeliveryLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: DeliveryAttributes.self) { context in
LockScreenView(context: context)
} dynamicIsland: { context in
DynamicIsland {
DynamicIslandExpandedContent {
ExpandedView(context: context)
}
} compactLeading: {
CompactLeadingView(context: context)
} compactTrailing: {
CompactTrailingView(context: context)
} minimal: {
MinimalView(context: context)
}
}
}
}
O Dynamic Island suporta interatividade — o utilizador toca na área e entra na app ou abre a vista expandida. Tocar no modo compacto muda para expandido, e deslizar para a esquerda minimiza a Activity. Os botões no modo expandido (pause/cancel) são manipulados através de Link do SwiftUI — o sistema inicia a app com um URL deep link, o processamento é feito no UIApplicationDelegate.
Limitações do Dynamic Island: a largura do modo expandido é até 300pt, o texto compacto até 30 caracteres. As cores e fontes correspondem ao tema do sistema — a personalização é limitada. As animações de transição entre modos são do sistema e não podem ser personalizadas. Se várias apps tiverem Activities ativas, o Dynamic Island exibe-as com prioridade baseada na hora de início e tipo de conteúdo.
Perguntas frequentes
Um widget normal do WidgetKit exibe informações estáticas e atualiza num temporizador do sistema com um intervalo mínimo de 15–30 minutos. A Live Activity mostra dados dinâmicos em tempo real no ecrã de bloqueio e Dynamic Island. A Live Activity é iniciada pela app, vive até 8 horas e é terminada pelo sistema após o fim do evento, ao contrário de um widget que existe permanentemente.
A Live Activity suporta dois modos de atualização: local — a app atualiza o estado através da API do ActivityKit a qualquer momento, e atualização push — o servidor envia uma notificação push do ActivityKit que o sistema converte num novo estado do widget. Quando a bateria está fraca, o sistema pode congelar a Live Activity até que o carregamento seja ligado.
As Live Activities estão disponíveis no iPhone com iOS 16.1 e versões posteriores. No iPhone 14 Pro e posteriores, a Live Activity também é exibida no Dynamic Island. No iPad, a Live Activity é suportada apenas no ecrã de bloqueio — o Dynamic Island não está disponível no iPad. O Apple Watch não suporta Live Activities diretamente, mas pode exibir notificações de conclusão.
O sistema limita o número de Live Activities ativas — normalmente não mais de 5 simultaneamente para todas as apps. Tentar iniciar além do limite devolve um erro do ActivityKit. Cada Live Activity pode ter vários estados — por exemplo, pendente, em trânsito, entregue para uma encomenda de comida. Após a conclusão, a Activity permanece na UI por mais 4 horas.
Sim, a app deve solicitar permissão para enviar notificações — a Live Activity utiliza o canal de notificações do sistema. O utilizador pode desativar a Live Activity para uma app específica nas definições. No primeiro início, o ActivityKit mostra um diálogo a solicitar permissão. Sem permissão, o pedido de Activity falha.
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