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 — структура с 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 поддържа два режима на актуализация: локален — приложението актуализира състоянието чрез API на ActivityKit по всяко време, и 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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също