Live Activity — динамички виџет на закључаном екрану iPhone-а и Dynamic Island-у, који приказује информације у реалном времену: статус доставе, спортске резултате, тајмере и репродукцију музике. Реализује се кроз ActivityKit (Swift, iOS 16.1+) заједно са WidgetKit-ом. Live Activity се ажурира локално или преко push обавештења, подржава више стања и систем га завршава након завршетка догађаја. Више на ActivityKit Documentation.
Главно
Live Activity — проширење WidgetKit-а које приказује динамички садржај на закључаном екрану iPhone-а и у Dynamic Island-у. За разлику од статичког виџета који се ажурира по системском тајмеру, Live Activity покреће апликација и живи ограничено време — до 8 сати за активну Activity и до 4 сата након завршетка. Корисник види актуелне податке без откључавања уређаја: статус поруџбине доставе, удаљеност до одредишта у таксију, резултат утакмице или напредак тренинга.
ActivityKit — фрејмворк за рад са Live Activities, представљен у iOS 16.1. Пружа API за захтевање, ажурирање и завршавање Activity. Activity је објекат са садржајем и стањем. Садржај (ActivityContent) дефинише статичке податке, а стање (ActivityState) — динамичке који се мењају током времена. Систем сам одлучује када да рендерује ново стање — то штеди батерију и гарантује глаткоћу анимација.
Свака Live Activity је јединствено идентификована ActivityID-ом и везана за један процес — апликацију која ју је креирала. Систем може да заврши Activity при недостатку меморије или ниском нивоу батерије. Програмер добија обавештење о присилном завршетку преко делегата ActivityKit-а и може да сачува последње стање за обнављање.
Архитектура Live Activity се заснива на два фрејмворка: WidgetKit је одговоран за рендеровање SwiftUI приказа, ActivityKit — за животни циклус Activity. Програмер креира WidgetBundle са подршком за LiveActivityConfiguration. Свака конфигурација дефинише тип података (Attributes и State) и SwiftUI View који систем рендерује на Lock Screen-у и Dynamic Island-у. Подаци се преносе преко ActivityAttributes — struct са let пољима за садржај и var пољима за стање.
| Компонента | Намена | API |
|---|---|---|
| Attributes | Статички подаци целе Activity | let name: String, let icon: String |
| ContentState | Динамичко стање које се мења при ажурирању | var progress: Double, var status: Status |
| Activity | Објекат за захтевање и управљање Activity | Activity.request(attributes:content:) |
| PushToken | Токен за серверска push ажурирања | activity.pushToken publisher |
| ActivityUI | SwiftUI View за Lock Screen и Dynamic Island | LockScreenView, ExpandedView, CompactView |
Животни циклус Activity укључује три фазе: активна (систем приказује и ажурира), финална (активност је завршена, али UI је још видљив 4 сата), уклоњена (систем уклања UI). Апликација може да заврши Activity у било ком тренутку. Систем такође присилно завршава Activity — на пример, при ресетовању уређаја или истеку 8-сатног ограничења.
import ActivityKit
struct DeliveryAttributes: ActivityAttributes {
public struct ContentState: Codable & Hashable {
var status: DeliveryStatus
var estimatedMinutes: Int
}
var orderNumber: String
var restaurantName: String
}
WidgetBundle региструје Live Activity преко макроа @main: виџет враћа листу конфигурација, укључујући LiveActivityConfiguration. На основу ове конфигурације, систем зна које типове података да очекује и како да рендерује UI у различитим стањима — компактном, минималном и проширеном за Dynamic Island.
Креирање Activity почиње захтевом према ActivityKit-у. Апликација позива Activity.request(attributes:content:pushType:) са почетним подацима. Систем проверава да ли је Dynamic Island доступан на уређају и враћа објекат Activity. Захтев може да не успе ако је прекорачен лимит активних Activity — обично не више од 5 истовремено. Након успешног захтева, систем приказује виџет на Lock Screen-у и, ако је могуће, у 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 за Live Activity користи структуре LockScreenView, ExpandedView и CompactView из WidgetKit-а. View добија контекст (ActivityViewContext) са тренутним атрибутима и стањем. Ажурирање View се дешава аутоматски при пријему новог стања од система. Live Activity подржава само ограничен скуп SwiftUI компонената — Text, Image, HStack, VStack и неколико модификатора.
Сваки Live Activity View мора бити лаган и брз — систем одбија да рендерује тешке приказе. Ограничење времена рендеровања — 30 ms по фрејму. Анимације су ограничене на системске прелазе између стања — прилагођене анимације у Live Activity нису доступне. Рендеровање се извршава у позадини процеса WidgetKit-а са приоритетом одзивности Lock Screen-а.
Локално ажурирање — апликација ажурира стање Activity позивом activity.update(using:). Метод прима нови ContentState и опциони AlertConfiguration за приказивање обавештења при ажурирању. Локална ажурирања су брза — систем поново исцртава View у следећем циклусу рендеровања, обично у року од 1–2 секунде. За честа ажурирања (тајмер, штоперица) користите локални режим — поузданији је и бржи од 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"
)
)
Push ажурирања — сервер шаље ActivityKit push обавештење са новим стањем у JSON формату. За ово апликација добија pushToken из activity.pushToken publisher-а и прослеђује га серверу. Сервер шаље POST захтев на APNs са payload-ом који садржи нови ContentState. Систем прима push, декодује стање и ажурира Live Activity без учешћа апликације — то омогућава ажурирање Activity чак и када је апликација затворена.
Push ажурирања су економичнија од локалних за ретка ажурирања (статус доставе сваких 5–10 минута) — апликација не мора да држи мрежну везу. За честа ажурирања сваких 1–2 секунде користите локални метод. Серверски payload садржи само променљива поља ContentState-а — статички подаци Attributes-а се шаљу само при креирању Activity.
Dynamic Island — хардверско-софтверска област на iPhone 14 Pro, 15 Pro и новијим која се прилагођава садржају Live Activity. Систем аутоматски приказује Activity у три режима: компактни (икона + кратак текст лево од изреза), минимални (само икона) и проширени (правоугаоник од 300pt са информацијама). Програмер не управља директно овим режимима — систем бира режим на основу приоритета и доступног простора.
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 подржава интерактивност — корисник додирује област и улази у апликацију или отвара проширени приказ. Притисак на компактни режим пребацује у проширени, а превлачење улево склања Activity у минимални. Дугмад у проширеном режиму (pause/cancel) се обрађују преко Link-а из SwiftUI-ја — систем покреће апликацију са deep link URL-ом, обрада се врши у UIApplicationDelegate-у.
Ограничења Dynamic Island-а: ширина проширеног режима — до 300pt, компактни текст — до 30 карактера. Боје и фонтови одговарају системској теми — прилагођавање је ограничено. Анимације прелаза између режима су системске и не могу се конфигурисати. Ако више апликација има активне Activity, Dynamic Island их приказује приоритетно по времену покретања и типу садржаја.
Често постављана питања
Обични WidgetKit виџет приказује статичке информације и ажурира се по системском тајмеру са минималним интервалом од 15–30 минута. Live Activity показује динамичке податке у реалном времену на закључаном екрану и Dynamic Island-у. Live Activity покреће апликација, живи до 8 сати и систем га завршава након завршетка догађаја, за разлику од виџета који постоји стално.
Live Activity подржава два режима ажурирања: локални — апликација ажурира стање преко ActivityKit API-ја у било ком тренутку, и push — сервер шаље ActivityKit push обавештење које систем претвара у ново стање виџета. При ниском нивоу батерије, систем може да замрзне Live Activity до прикључивања пуњача.
Live Activities су доступне на iPhone-у са iOS 16.1 и новијим. На iPhone 14 Pro и новијим, Live Activity се такође приказује у Dynamic Island-у. На iPad-у, Live Activity је подржан само на закључаном екрану — Dynamic Island на iPad-у не постоји. Apple Watch не подржава Live Activities директно, али може да приказује обавештења о завршетку.
Систем ограничава број активних Live Activities — обично не више од 5 истовремено за све апликације. При покушају прекорачења лимита, ActivityKit враћа грешку. Свака Live Activity може имати више стања — на пример, чекање, у транзиту, достављено за поруџбину хране. Након завршетка, Activity остаје у UI још 4 сата.
Да, апликација мора да затражи дозволу за слање обавештења — Live Activity користи системски канал обавештења. Корисник може да искључи Live Activity за одређену апликацију у подешавањима. При првом покретању, ActivityKit приказује дијалог са захтевом за дозволу. Без дозволе, захтев Activity се завршава грешком.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође