Live Activity è un widget dinamico sulla schermata di blocco dell'iPhone e in Dynamic Island che mostra informazioni in tempo reale: stato della consegna, punteggi sportivi, timer e riproduzione musicale. Viene implementata tramite ActivityKit (Swift, iOS 16.1+) insieme a WidgetKit. Live Activity si aggiorna localmente o tramite notifiche push, supporta più stati e viene terminata dal sistema dopo la fine dell'evento. Scopri di più su ActivityKit Documentation.
Punti chiave
Live Activity è un'estensione di WidgetKit che mostra contenuti dinamici sulla schermata di blocco dell'iPhone e in Dynamic Island. A differenza di un widget statico che si aggiorna su un timer di sistema, Live Activity viene avviata dall'app e vive per un tempo limitato — fino a 8 ore per un'Activity attiva e fino a 4 ore dopo il completamento. L'utente vede dati aggiornati senza sbloccare il dispositivo: stato dell'ordine di consegna, distanza dalla destinazione in un taxi, risultati di una partita o progresso dell'allenamento.
ActivityKit è un framework per lavorare con Live Activities, introdotto in iOS 16.1. Fornisce un'API per richiedere, aggiornare e terminare Activities. Un'Activity è un oggetto con contenuto e stato. Il contenuto (ActivityContent) definisce dati statici, mentre lo stato (ActivityState) definisce dati dinamici che cambiano nel tempo. Il sistema stesso decide quando rendere il nuovo stato — questo risparmia la batteria e garantisce animazioni fluide.
Ogni Live Activity è identificata in modo univoco da un ActivityID ed è legata a un processo — l'app che l'ha creata. Il sistema può terminare l'Activity quando la memoria è scarsa o la carica della batteria è bassa. Lo sviluppatore riceve una notifica di terminazione forzata tramite il delegato ActivityKit e può salvare l'ultimo stato per il ripristino.
L'architettura di Live Activity è basata su due framework: WidgetKit è responsabile del rendering delle viste SwiftUI, ActivityKit gestisce il ciclo di vita dell'Activity. Lo sviluppatore crea un WidgetBundle con supporto per LiveActivityConfiguration. Ogni configurazione definisce il tipo di dati (Attributes e State) e una vista SwiftUI che il sistema rende sulla schermata di blocco e in Dynamic Island. I dati vengono passati tramite ActivityAttributes — una struct con campi let per il contenuto e campi var per lo stato.
| Componente | Scopo | API |
|---|---|---|
| Attributes | Dati statici dell'intera Activity | let name: String, let icon: String |
| ContentState | Stato dinamico, modificabile all'aggiornamento | var progress: Double, var status: Status |
| Activity | Oggetto di richiesta e gestione dell'Activity | Activity.request(attributes:content:) |
| PushToken | Token per aggiornamenti push dal server | activity.pushToken publisher |
| ActivityUI | Vista SwiftUI per schermata di blocco e Dynamic Island | LockScreenView, ExpandedView, CompactView |
Ciclo di vita dell'Activity include tre fasi: attiva (il sistema mostra e aggiorna), finale (l'attività è terminata ma l'UI è ancora visibile per 4 ore), rimossa (il sistema rimuove l'UI). L'app può terminare l'Activity in qualsiasi momento. Il sistema termina anche le Activities forzatamente — ad esempio, al riavvio del dispositivo o alla scadenza del limite di 8 ore.
import ActivityKit
struct DeliveryAttributes: ActivityAttributes {
public struct ContentState: Codable & Hashable {
var status: DeliveryStatus
var estimatedMinutes: Int
}
var orderNumber: String
var restaurantName: String
}
WidgetBundle registra Live Activity tramite la macro @main: il widget restituisce un elenco di configurazioni inclusa LiveActivityConfiguration. Sulla base di questa configurazione, il sistema sa quali tipi di dati aspettarsi e come rendere l'UI in diversi stati — compatto, minimo ed espanso per Dynamic Island.
Creare un'Activity inizia con una richiesta ad ActivityKit. L'app chiama Activity.request(attributes:content:pushType:) con dati iniziali. Il sistema verifica se Dynamic Island è disponibile sul dispositivo e restituisce un oggetto Activity. La richiesta potrebbe fallire se il limite di Activities attive viene superato — di solito non più di 5 simultaneamente. Dopo una richiesta riuscita, il sistema mostra il widget sulla schermata di blocco e, se disponibile, in 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)")
}
La vista SwiftUI per Live Activity utilizza le strutture LockScreenView, ExpandedView e CompactView di WidgetKit. La vista riceve il contesto (ActivityViewContext) con attributi e stato correnti. L'aggiornamento della vista avviene automaticamente quando un nuovo stato arriva dal sistema. Live Activity supporta solo un insieme limitato di componenti SwiftUI — Text, Image, HStack, VStack e alcuni modificatori.
Ogni vista Live Activity deve essere leggera e veloce — il sistema rifiuta di rendere viste pesanti. Il limite di tempo di rendering è di 30 ms per fotogramma. Le animazioni sono limitate alle transizioni di sistema tra stati — le animazioni personalizzate non sono disponibili in Live Activity. Il rendering viene eseguito in un processo in background di WidgetKit con priorità di reattività della schermata di blocco.
Aggiornamento locale — l'app aggiorna lo stato dell'Activity chiamando activity.update(using:). Il metodo accetta un nuovo ContentState e un AlertConfiguration opzionale per mostrare una notifica all'aggiornamento. Gli aggiornamenti locali sono veloci — il sistema ridisegna la vista al prossimo ciclo di rendering, di solito entro 1–2 secondi. Per aggiornamenti frequenti (timer, cronometro) usa la modalità locale — è più affidabile e veloce del 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"
)
)
Aggiornamenti push — il server invia una notifica push ActivityKit con il nuovo stato in formato JSON. Per questo, l'app riceve un pushToken dal publisher activity.pushToken e lo passa al server. Il server invia una richiesta POST agli APNs con un payload contenente il nuovo ContentState. Il sistema riceve il push, decodifica lo stato e aggiorna Live Activity senza coinvolgimento dell'app — questo permette di aggiornare l'Activity anche quando l'app è chiusa.
Gli aggiornamenti push sono più efficienti di quelli locali per aggiornamenti poco frequenti (stato di consegna ogni 5–10 minuti) — l'app non deve mantenere una connessione di rete. Per aggiornamenti frequenti ogni 1–2 secondi usa il metodo locale. Il payload del server include solo i campi mutabili di ContentState — i dati statici di Attributes vengono inviati solo alla creazione dell'Activity.
Dynamic Island è un'area hardware-software su iPhone 14 Pro, 15 Pro e successivi che si adatta al contenuto di Live Activity. Il sistema mostra automaticamente l'Activity in tre modalità: compatta (icona + testo breve a sinistra del ritaglio), minima (solo icona) ed espansa (rettangolo di 300pt con informazioni). Lo sviluppatore non controlla direttamente queste modalità — il sistema seleziona la modalità in base alla priorità e allo spazio disponibile.
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)
}
}
}
}
Dynamic Island supporta l'interattività — l'utente tocca l'area ed entra nell'app o apre la vista espansa. Toccare la modalità compatta passa a quella espansa, e scorrere verso sinistra riduce l'Activity alla modalità minima. I pulsanti in modalità espansa (pausa/annulla) vengono gestiti tramite Link da SwiftUI — il sistema avvia l'app con un URL deep link, l'elaborazione viene eseguita in UIApplicationDelegate.
Limitazioni di Dynamic Island: la larghezza della modalità espansa è fino a 300pt, il testo compatto fino a 30 caratteri. Colori e caratteri corrispondono al tema di sistema — la personalizzazione è limitata. Le animazioni di transizione tra le modalità sono definite dal sistema e non possono essere personalizzate. Se più app hanno Activities attive, Dynamic Island le mostra con priorità basata sull'ora di avvio e sul tipo di contenuto.
Domande frequenti
Un widget WidgetKit normale mostra informazioni statiche e si aggiorna su un timer di sistema con un intervallo minimo di 15–30 minuti. Live Activity mostra dati dinamici in tempo reale sulla schermata di blocco e Dynamic Island. Live Activity viene avviata dall'app, vive fino a 8 ore e viene terminata dal sistema dopo la fine dell'evento, a differenza di un widget che esiste permanentemente.
Live Activity supporta due modalità di aggiornamento: locale — l'app aggiorna lo stato tramite l'API ActivityKit in qualsiasi momento, e aggiornamento push — il server invia una notifica push ActivityKit che il sistema converte in un nuovo stato del widget. Quando la batteria è scarica, il sistema può congelare Live Activity fino a quando non viene collegato il caricabatterie.
Le Live Activities sono disponibili su iPhone con iOS 16.1 e versioni successive. Su iPhone 14 Pro e successivi, Live Activity viene visualizzata anche in Dynamic Island. Su iPad, Live Activity è supportata solo sulla schermata di blocco — Dynamic Island non è disponibile su iPad. Apple Watch non supporta direttamente le Live Activities, ma può mostrare notifiche di completamento.
Il sistema limita il numero di Live Activities attive — di solito non più di 5 contemporaneamente per tutte le app. Tentare di avviarne oltre il limite restituisce un errore da ActivityKit. Ogni Live Activity può avere più stati — ad esempio, in attesa, in transito, consegnato per un ordine di cibo. Dopo il completamento, l'Activity rimane nell'UI per altre 4 ore.
Sì, l'app deve richiedere il permesso per inviare notifiche — Live Activity utilizza il canale di notifiche di sistema. L'utente può disabilitare Live Activity per un'app specifica nelle impostazioni. Al primo avvio, ActivityKit mostra un dialogo che richiede il permesso. Senza permesso, la richiesta di Activity fallisce.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche