Live Activity — dynamiczny widżet na ekranie blokady iPhone'a i w Dynamic Island, wyświetlający informacje w czasie rzeczywistym: status dostawy, wyniki sportowe, timery i odtwarzanie muzyki. Implementowany przez ActivityKit (Swift, iOS 16.1+) wraz z WidgetKit. Live Activity jest aktualizowany lokalnie lub przez powiadomienia push, obsługuje kilka stanów i jest kończony przez system po zakończeniu zdarzenia. Więcej na ActivityKit Documentation.
Najważniejsze
Live Activity — rozszerzenie WidgetKit, wyświetlające dynamiczną treść na ekranie blokady iPhone'a i w Dynamic Island. W przeciwieństwie do statycznego widżetu, który aktualizuje się według timera systemowego, Live Activity jest uruchamiany przez aplikację i żyje przez ograniczony czas — do 8 godzin dla aktywnej Activity i do 4 godzin po zakończeniu. Użytkownik widzi aktualne dane bez odblokowywania urządzenia: status zamówienia dostawy, odległość do celu w taksówce, wynik meczu lub postęp treningu.
ActivityKit — framework do pracy z Live Activities, wprowadzony w iOS 16.1. Udostępnia API do żądania, aktualizowania i kończenia Activity. Activity to obiekt z treścią i stanem. Treść (ActivityContent) określa dane statyczne, a stan (ActivityState) — dynamiczne, zmieniające się w czasie. System sam decyduje, kiedy wyrenderować nowy stan — oszczędza to baterię i gwarantuje płynność animacji.
Każda Live Activity jest jednoznacznie identyfikowana przez ActivityID i powiązana z jednym procesem — aplikacją, która ją utworzyła. System może zakończyć Activity przy braku pamięci lub niskim poziomie baterii. Deweloper otrzymuje powiadomienie o wymuszonym zakończeniu przez delegat ActivityKit i może zapisać ostatni stan do przywrócenia.
Architektura Live Activity opiera się na dwóch frameworkach: WidgetKit odpowiada za renderowanie SwiftUI widoków, ActivityKit — za cykl życia Activity. Deweloper tworzy WidgetBundle z obsługą LiveActivityConfiguration. Każda konfiguracja określa typ danych (Attributes i State) oraz SwiftUI View, która jest renderowana przez system na Lock Screen i Dynamic Island. Dane są przesyłane przez ActivityAttributes — struct z polami let dla treści i var dla stanu.
| Komponent | Przeznaczenie | API |
|---|---|---|
| Attributes | Statyczne dane całej Activity | let name: String, let icon: String |
| ContentState | Stan dynamiczny, zmieniany przy aktualizacji | var progress: Double, var status: Status |
| Activity | Obiekt żądania i zarządzania Activity | Activity.request(attributes:content:) |
| PushToken | Token do serwerowych aktualizacji push | activity.pushToken publisher |
| ActivityUI | SwiftUI View dla Lock Screen i Dynamic Island | LockScreenView, ExpandedView, CompactView |
Cykl życia Activity obejmuje trzy fazy: aktywna (system wyświetla i aktualizuje), finalna (aktywność zakończona, ale UI jest widoczne przez 4 godziny), usunięta (system usuwa UI). Aplikacja może zakończyć Activity w dowolnym momencie. System również kończy Activity przymusowo — na przykład przy restarcie urządzenia lub po przekroczeniu 8-godzinnego limitu.
import ActivityKit
struct DeliveryAttributes: ActivityAttributes {
public struct ContentState: Codable & Hashable {
var status: DeliveryStatus
var estimatedMinutes: Int
}
var orderNumber: String
var restaurantName: String
}
WidgetBundle rejestruje Live Activity przez makro @main: widżet zwraca listę konfiguracji, w tym LiveActivityConfiguration. System na podstawie tej konfiguracji wie, jakich typów danych oczekiwać i jak renderować UI w różnych stanach — kompaktowym, minimalnym i rozszerzonym dla Dynamic Island.
Tworzenie Activity rozpoczyna się od żądania do ActivityKit. Aplikacja wywołuje Activity.request(attributes:content:pushType:) z danymi początkowymi. System sprawdza, czy Dynamic Island jest dostępny na urządzeniu i zwraca obiekt Activity. Żądanie może zakończyć się błędem, jeśli przekroczono limit aktywnych Activity — zwykle nie więcej niż 5 jednocześnie. Po pomyślnym żądaniu system wyświetla widżet na Lock Screen i, jeśli to możliwe, w 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)")
}
SwiftUI View dla Live Activity używa struktur LockScreenView, ExpandedView i CompactView z WidgetKit. View otrzymuje kontekst (ActivityViewContext) z bieżącymi atrybutami i stanem. Aktualizacja View następuje automatycznie po otrzymaniu nowego stanu od systemu. Live Activity obsługuje tylko ograniczony zestaw komponentów SwiftUI — Text, Image, HStack, VStack i kilka modyfikatorów.
Każdy Live Activity View musi być lekki i szybki — system odmawia renderowania ciężkich widoków. Ograniczenie czasu renderowania — 30 ms na klatkę. Animacje są ograniczone do systemowych przejść między stanami — niestandardowe animacje w Live Activity są niedostępne. Renderowanie odbywa się w tle procesu WidgetKit z priorytetem responsywności Lock Screen.
Aktualizacja lokalna — aplikacja aktualizuje stan Activity wywołaniem activity.update(using:). Metoda przyjmuje nowy ContentState i opcjonalny AlertConfiguration do wyświetlenia powiadomienia przy aktualizacji. Lokalne aktualizacje są szybkie — system przerysowuje View w następnym cyklu renderowania, zwykle w ciągu 1–2 sekund. Do częstych aktualizacji (timer, stoper) używaj trybu lokalnego — jest niezawodniejszy i szybszy niż 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"
)
)
Aktualizacje push — serwer wysyła powiadomienie push ActivityKit z nowym stanem w formacie JSON. Aplikacja otrzymuje pushToken z activity.pushToken publisher i przekazuje go na serwer. Serwer wysyła żądanie POST do APNs z payloadem zawierającym nowy ContentState. System otrzymuje push, dekoduje stan i aktualizuje Live Activity bez udziału aplikacji — pozwala to aktualizować Activity nawet gdy aplikacja jest zamknięta.
Aktualizacje push są bardziej oszczędne niż lokalne dla rzadkich aktualizacji (status dostawy co 5–10 minut) — aplikacja nie musi utrzymywać połączenia sieciowego. Do częstych aktualizacji co 1–2 sekundy używaj metody lokalnej. Payload serwera zawiera tylko zmienne pola ContentState — statyczne dane Attributes są wysyłane tylko przy tworzeniu Activity.
Dynamic Island — obszar sprzętowo-programowy na iPhone 14 Pro, 15 Pro i nowszych, który dostosowuje się do treści Live Activity. System automatycznie wyświetla Activity w trzech trybach: kompaktowym (ikona + krótki tekst po lewej stronie wycięcia), minimalnym (tylko ikona) i rozszerzonym (prostokąt 300pt z informacjami). Deweloper nie zarządza tymi trybami bezpośrednio — system wybiera tryb na podstawie priorytetu i dostępnego miejsca.
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 obsługuje interaktywność — użytkownik dotyka obszaru i przechodzi do aplikacji lub otwiera rozszerzony widok. Naciśnięcie trybu kompaktowego przełącza na rozszerzony, a przesunięcie w lewo ukrywa Activity do minimalnego. Przyciski w trybie rozszerzonym (pause/cancel) są obsługiwane przez Link z SwiftUI — system uruchamia aplikację z deep link URL, obsługa odbywa się w UIApplicationDelegate.
Ograniczenia Dynamic Island: szerokość trybu rozszerzonego — do 300pt, tekst kompaktowy — do 30 znaków. Kolory i czcionki odpowiadają motywowi systemowemu — dostosowanie jest ograniczone. Animacje przejść między trybami są systemowe i nie można ich konfigurować. Jeśli kilka aplikacji ma aktywne Activity, Dynamic Island wyświetla je z priorytetem według czasu uruchomienia i typu treści.
Często zadawane pytania
Zwykły widżet WidgetKit wyświetla statyczne informacje i aktualizuje się według timera systemowego z minimalnym interwałem 15–30 minut. Live Activity pokazuje dynamiczne dane w czasie rzeczywistym na ekranie blokady i Dynamic Island. Live Activity jest uruchamiany przez aplikację, żyje do 8 godzin i jest kończony przez system po zakończeniu zdarzenia, w przeciwieństwie do widżetu, który istnieje stale.
Live Activity obsługuje dwa tryby aktualizacji: lokalny — aplikacja aktualizuje stan przez ActivityKit API w dowolnym momencie, i push — serwer wysyła powiadomienie push ActivityKit, które system przekształca w nowy stan widżetu. Przy niskim poziomie baterii system może zamrozić Live Activity do momentu podłączenia ładowania.
Live Activities są dostępne na iPhone z iOS 16.1 i nowszym. Na iPhone 14 Pro i nowszych Live Activity wyświetla się również w Dynamic Island. Na iPadzie Live Activity jest obsługiwane tylko na ekranie blokady — Dynamic Island na iPadzie nie występuje. Apple Watch nie obsługują Live Activities bezpośrednio, ale mogą wyświetlać powiadomienia o zakończeniu.
System ogranicza liczbę aktywnych Live Activities — zwykle nie więcej niż 5 jednocześnie dla wszystkich aplikacji. Przy próbie uruchomienia powyżej limitu ActivityKit zwraca błąd. Każda Live Activity może mieć kilka stanów — na przykład oczekiwanie, w drodze, dostarczone dla zamówienia jedzenia. Po zakończeniu Activity pozostaje w UI przez kolejne 4 godziny.
Tak, aplikacja musi poprosić o zgodę na wysyłanie powiadomień — Live Activity korzysta z systemowego kanału powiadomień. Użytkownik może wyłączyć Live Activity dla konkretnej aplikacji w ustawieniach. Przy pierwszym uruchomieniu ActivityKit system wyświetla dialog z prośbą o zgodę. Bez zgody żądanie Activity kończy się błędem.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również