Live Activity для відстеження цени криптовалюти на iOS
Live Activities з'явилися у iOS 16.1 і дають принципово інший спосіб показувати актуальні дані — не просто віджет на Home Screen, а постійно оновлювана плашка на Lock Screen та у Dynamic Island (iPhone 14 Pro та новіші). Для трейдинг-додатків та крипто-кошельків це точка входу, яку користувач бачить без відкриття додатку.
ActivityKit та обмеження
Live Activity створюється через ActivityKit. Важливо розуміти принципове обмеження перед стартом: Activity можна запустити тільки з самого додатку, коли він на передньому плані. Неможливо стартувати Activity з фонового процесу або push-уведомлення. Оновлювати — можна через ActivityKit API або через push (ActivityKit Push Update).
Максимальний час життя однієї Activity — 12 годин (система може завершити раніше). Дані ActivityAttributes — статичні на все життя. Дані ContentState — динамічні, саме вони оновлюються.
Для крипто-віджета архітектура виглядає так:
struct CryptoActivityAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
var price: Double
var change24h: Double
var lastUpdated: Date
}
var symbol: String // статично: BTC, ETH тощо
var baseCurrency: String // статично: USD
}
Запуск та оновлення
let attributes = CryptoActivityAttributes(symbol: "BTC", baseCurrency: "USD")
let initialState = CryptoActivityAttributes.ContentState(
price: 67_430.0,
change24h: 2.3,
lastUpdated: .now
)
let activity = try Activity<CryptoActivityAttributes>.request(
attributes: attributes,
content: .init(state: initialState, staleDate: Date().addingTimeInterval(60)),
pushType: .token // якщо плануємо оновлювати через push
)
staleDate — момент, коли система вважає дані застарілими і може показати спеціальний UI. Для ціни крипти ставимо 60–120 секунд.
Оновлення через локальний код:
let updatedState = CryptoActivityAttributes.ContentState(
price: newPrice,
change24h: newChange,
lastUpdated: .now
)
await activity.update(.init(state: updatedState, staleDate: Date().addingTimeInterval(60)))
Оновлення через ActivityKit Push
Для real-time оновлень ціни потрібен бекенд, який отправляет ActivityKit Push Notification — це окремий тип push, не APNs-уведомлення. Payload виглядає так:
{
"aps": {
"timestamp": 1699000000,
"event": "update",
"content-state": {
"price": 68100.0,
"change24h": 2.8,
"lastUpdated": 1699000000
},
"alert": {
"title": "BTC",
"body": "$68,100"
}
}
}
Токен для ActivityKit Push — окремий від звичайного APNs-токена. Додаток отримує його через activity.pushTokenUpdates і повинен відправити на сервер. Якщо токен не оновлюється на сервері після перезапуску Activity — оновлення перестають приходити.
Dynamic Island: компактний та розгорнутий вид
SwiftUI-вёрстка для Dynamic Island ділиться на кілька представлень: compactLeading, compactTrailing, minimal, expanded. Кожне — окремий SwiftUI View. Обмеження по розміру для compact-видів жорстке — буквально кілька пікселів, ніяких списків.
.dynamicIsland { context in
DynamicIsland {
DynamicIslandExpandedRegion(.leading) {
Text(context.attributes.symbol).font(.headline)
}
DynamicIslandExpandedRegion(.trailing) {
Text(context.state.change24h >= 0 ? "↑" : "↓")
.foregroundColor(context.state.change24h >= 0 ? .green : .red)
}
DynamicIslandExpandedRegion(.center) {
Text("$\(context.state.price, format: .number.precision(.fractionLength(2)))")
.font(.title2)
}
} compactLeading: {
Text(context.attributes.symbol).font(.caption2)
} compactTrailing: {
Text("$\(Int(context.state.price))").font(.caption2)
} minimal: {
Text(context.attributes.symbol.prefix(1))
}
}
Що входить у роботу
- Створення ActivityKit extension з
ActivityAttributesтаContentState - SwiftUI-вёрстка для Lock Screen, Dynamic Island (compact, minimal, expanded)
- Запуск та завершення Activity з основного додатку
- Налаштування ActivityKit Push оновлень (потребує серверної частини)
- Обробка застарівання даних (
staleDate) - Тестування на iPhone з і без Dynamic Island
Графік
2–3 дні для UI-частини з локальними оновленнями. Інтеграція з сервером для push-оновлень — плюс 1–2 дні. Вартість розраховується індивідуально після аналізу вимог.







