Виджет цены криптовалюты для Home Screen (iOS и Android)
Виджет на главном экране — это отдельный процесс, который живёт независимо от основного приложения. Это не компонент внутри приложения и не фоновый сервис с доступом к сети в любой момент. На iOS это WidgetKit + SwiftUI, на Android — Jetpack Glance или классический AppWidgetProvider. Оба работают по принципу snapshot: система запрашивает актуальный UI в определённые моменты, и то, что отобразится — ваша ответственность.
iOS: WidgetKit и ограничения обновлений
WidgetKit не разрешает виджету делать сетевые запросы в реальном времени. Виджет получает данные через TimelineProvider, который возвращает массив TimelineEntry с заранее подготовленными данными и временными метками. Система сама решает, когда перерисовать виджет.
Для криптовиджета типичная стратегия — обновление каждые 15–30 минут через TimelineReloadPolicy.atEnd или .after(date:):
struct CryptoPriceEntry: TimelineEntry {
let date: Date
let symbol: String
let price: Decimal
let change24h: Double
}
struct CryptoPriceProvider: TimelineProvider {
func getTimeline(in context: Context,
completion: @escaping (Timeline<CryptoPriceEntry>) -> Void) {
Task {
let price = try? await CryptoAPIClient.shared.fetchPrice(symbol: "BTC")
let entry = CryptoPriceEntry(date: .now,
symbol: "BTC",
price: price?.usd ?? 0,
change24h: price?.change24h ?? 0)
let nextUpdate = Calendar.current.date(byAdding: .minute, value: 15, to: .now)!
let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
completion(timeline)
}
}
}
Важный нюанс: Apple регулирует бюджет обновлений. Виджет с высокой частотой обновлений на устройствах с низким зарядом батареи получает урезанный бюджет — обновления начинают приходить реже, чем запрошено. Для трейдинг-приложений с требованием «данные не старше 1 минуты» WidgetKit подходит плохо — нужно честно объяснить это клиенту до начала разработки.
Передача данных между основным приложением и виджетом — через App Groups + UserDefaults(suiteName:) или FileManager с shared container. @AppStorage внутри виджета работает только с App Group suite — без этого виджет не увидит данные, записанные основным приложением.
Размеры и адаптация UI
WidgetKit поддерживает 4 размера: .systemSmall, .systemMedium, .systemLarge, .systemExtraLarge (только iPad). Для криптовиджета обычно делаем small (символ + цена + изменение) и medium (несколько монет в строку). SwiftUI в виджете не поддерживает анимации, ScrollView, нажатия на произвольные области — только Link для deep link.
Android: Jetpack Glance
Jetpack Glance — Compose-подобный API для виджетов, появился в 2022 году. Заметно удобнее классического RemoteViews, но имеет ограничения: поддерживаются не все Compose-модификаторы, а часть API работает иначе, чем в обычном Compose.
Обновление данных через GlanceAppWidgetManager.updateIf + WorkManager с периодической задачей:
class CryptoPriceWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
val prefs = currentState<Preferences>()
val price = prefs[priceKey] ?: "—"
val change = prefs[changeKey] ?: "0.0"
provideContent {
Column(
modifier = GlanceModifier.fillMaxSize().background(Color.DarkGray).padding(12.dp)
) {
Text("BTC", style = TextStyle(color = ColorProvider(Color.White), fontSize = 12.sp))
Text(price, style = TextStyle(color = ColorProvider(Color.White), fontSize = 20.sp))
Text("$change%", style = TextStyle(
color = ColorProvider(if (change.startsWith("-")) Color.Red else Color.Green)
))
}
}
}
}
Минимальный интервал обновления через AppWidgetManager — 30 минут (ограничение Android). Для более частых обновлений нужен WorkManager с PeriodicWorkRequest, но на Android 12+ фоновые задачи регулируются Battery Optimizer — в Doze mode интервалы растягиваются.
Что входит в работу
- iOS: WidgetKit extension,
TimelineProvider, SwiftUI-вёрстка, App Groups для shared data - Android: Jetpack Glance widget, WorkManager для обновлений
- Интеграция с API курсов (CoinGecko, Binance, CoinMarketCap или собственный бэкенд)
- Поддержка нескольких размеров виджета
- Deep link из виджета в нужный экран приложения
- Тестирование поведения при отсутствии сети и устаревших данных
Сроки
3–5 дней на каждую платформу. Если нужны обе — 5–8 дней суммарно с учётом общей логики получения данных. Стоимость рассчитывается индивидуально.







