WidgetKit — це фреймворк Apple, представлений в iOS 14, який дозволяє розробникам розміщувати динамічні віджети на домашньому екрані iPhone та iPad, робочому столі Mac та циферблаті Apple Watch. Віджети відображають ключову інформацію без відкриття застосунку — прогноз погоди, курс валют, календар, кроки. За даними Apple Developer Documentation, 2026, WidgetKit обробляє до 2 мільярдів оновлень віджетів щодня в екосистемі Apple, що робить його одним із найбільш використовуваних фреймворків для відображення інформації на системних екранах.
Головне
WidgetKit — фреймворк Apple для створення віджетів, які відображають вміст на системних екранах пристроїв Apple. Віджет — це мініатюрне представлення вашого застосунку, яке користувач розміщує на домашньому екрані в режимі «тряски» (jiggle mode). На відміну від watchOS-комплікацій, які існували до WidgetKit, новий фреймворк уніфікував створення віджетів для всіх платформ Apple через єдиний API на SwiftUI.
Принцип роботи WidgetKit базується на TimelineProvider — об'єкті, який створює впорядкований масив TimelineEntry, де кожен запис містить Snapshot (конкретний стан віджета у визначений момент часу). Система відображає записи послідовно, оновлюючи віджет при переході до наступного запису на часовій шкалі. Між записами WidgetKit не викликає код застосунку — процесорний час витрачається лише при створенні нового Timeline.
За даними WWDC 2024 Session «WidgetKit: What’s new», середній користувач iOS має на домашньому екрані 8–12 віджетів, а найпопулярніші категорії — погода, час, календар, фітнес та фінанси. WidgetKit споживає менше 1% заряду батареї на день при типовому використанні завдяки тому, що оновлення відбуваються за розкладом, а не в реальному часі.
До iOS 14 віджети існували лише у вигляді Today View — панелі, доступної свайпом вліво від першого екрана. Today Extensions мали серйозні обмеження: вони були доступні лише на екрані «Сьогодні», вимагали відкриття застосунку для оновлення вмісту та мали обмежену підтримку розмірів. WidgetKit повністю замінив Today Extensions, надавши віджети на домашньому екрані, екрані блокування (iOS 16+) та робочому столі Mac.
Архітектура WidgetKit будується на трьох ключових протоколах: TimelineProvider, TimelineEntry та Widget. TimelineEntry — це модель даних, що представляє стан віджета у конкретний момент часу. TimelineProvider створює масив таких записів (Timeline), вказуючи дату активації для кожного. Widget — точка входу, яка пов'язує провайдера з представленням SwiftUI.
Метод Timeline getTimeline викликається системою при першому додаванні віджета, а потім періодично — зазвичай кожні 1–6 годин залежно від типу провайдера. Timeline може містити записи на години або дні вперед, що дозволяє віджету працювати без виклику коду застосунку між оновленнями. Якщо необхідно терміново оновити віджет (наприклад, змінився курс валют), застосунок може викликати WidgetCenter.shared.reloadAllTimelines() примусово.
struct SimpleEntry: TimelineEntry {
let date: Date
let value: Double
}
struct Provider: TimelineProvider {
typealias Entry = SimpleEntry
func placeholder(in context: Context) -> Entry {
Entry(date: Date(), value: 0)
}
func getSnapshot(
in context: Context,
completion: @escaping (Entry) -> Void
) {
Entry(date: Date(), value: 42.5)
}
func getTimeline(
in context: Context,
completion: @escaping (Timeline<Entry>, Error?) -> Void
) {
let entry = Entry(date: Date(), value: fetchLatestValue())
let nextUpdate = Calendar.current
.date(byAdding: .hour, value: 1, to: Date())!
let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
completion(timeline, nil)
}
}
WidgetKit підтримує три розміри віджетів, кожен з яких має фіксовані пропорції. Small (170×170 pt на iPhone) відображає компактну інформацію — одне значення, іконку або короткий текст. Medium (364×170 pt) вдвічі ширший за small і підходить для відображення пари значень або міні-графіка. Large (364×382 pt) займає майже половину екрана по вертикалі та дозволяє відображати таблиці, списки або розгорнуті дані.
Розробник зобов'язаний підтримувати хоча б два розміри — Apple рекомендує small + medium. Large віджет потрібен лише якщо застосунок має достатньо вмісту для заповнення такого обсягу. Кожен розмір отримує власне SwiftUI View, яке WidgetKit рендерить на системному екрані. Важливо, що WidgetKit не підтримує кастомні розміри — лише три фіксованих, що гарантує єдність інтерфейсу.
struct WeatherWidget: Widget {
let kind: String = "WeatherWidget"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
WeatherWidgetView(entry: entry)
}
.configurationDisplayName("Weather")
.description("Current temperature and forecast")
.supportedFamilies([.systemSmall, .systemMedium])
}
}
WidgetKit пропонує два типи конфігурації — StaticConfiguration та IntentConfiguration. StaticConfiguration підходить для віджетів, які відображають однаковий вміст для всіх користувачів: курси валют, погода, календар. IntentConfiguration дозволяє користувачеві налаштовувати віджет при додаванні через систему інтентів Siri — наприклад, вибрати конкретне місто для погоди або конкретний тікер для курсу акцій.
IntentConfiguration використовує INWidgetIntent — підклас INIntent з SiriKit. Коли користувач додає віджет та вибирає параметри (наприклад, місто), система зберігає цей інтент і передає його в TimelineProvider при кожному оновленні. Провайдер отримує інтент у методі getTimeline та використовує його параметри для формування вмісту. IntentConfiguration — кращий спосіб для персоналізованих віджетів, оскільки він інтегрується з Siri та Shortcuts.
struct WeatherWidgetEntryView: View {
var entry: WeatherEntry
var body: some View {
VStack(alignment: .leading) {
Text(entry.cityName)
.font(.caption)
.foregroundColor(.secondary)
Text("\(entry.temperature)°C")
.font(.largeTitle)
}
}
}
struct WeatherWidget: Widget {
var body: some WidgetConfiguration {
IntentConfiguration(
kind: "WeatherWidget",
intent: WeatherConfigIntent.self,
provider: WeatherTimelineProvider()
) { entry in
WeatherWidgetEntryView(entry: entry)
}
}
}
Створення віджета починається з додавання Widget Extension Target в Xcode: File → New → Target → Widget Extension. Xcode автоматично генерує структуру з TimelineEntry, TimelineProvider та WidgetConfiguration. Розробнику залишається лише реалізувати SwiftUI View для відображення даних та налаштувати провайдера для коректного розкладу оновлень.
Нижче — повний приклад простого віджета для відображення поточного курсу біткоїна: Provider завантажує курс через URLSession та створює Timeline з оновленням щогодини. WidgetSwiftUIView відображає курс великим шрифтом та час останнього оновлення дрібним шрифтом.
struct BTCPriceEntry: TimelineEntry {
let date: Date
let price: Double
let change24h: Double
}
struct BTCWidgetEntryView: View {
var entry: BTCPriceEntry
var body: some View {
VStack {
Text("BTC/USD").font(.caption)
Text("$\(entry.price, specifier: "%.0f")")
.font(.title2).fontWeight(.bold)
Text(entry.change24h > 0 ? "+" : "")
}
}
}
З iOS 16 WidgetKit розширив підтримку на Екран блокування — екран блокування iPhone. Віджети екрана блокування бувають двох типів: inline (один рядок тексту під годинником) та rectangular (прямокутна область). На відміну від віджетів домашнього екрана, віджети екрана блокування оновлюються частіше — системний тригер дозволяє оновлювати їх кожні 15–30 хвилин для відображення актуальної інформації без розблокування телефону.
Віджети екрана блокування вимагають окремої конфігурації через WidgetConfiguration з accessoryFamilies: accessoryCircular, accessoryRectangular, accessoryInline. Ці сімейства мають суворі обмеження щодо розміру та вмісту — вони не підтримують зображення, анімацію та кастомні шрифти. Apple рекомендує використовувати лише текстову інформацію та системні іконки SF Symbols для віджетів екрана блокування.
При розробці віджетів важливо враховувати обмеження WidgetKit. Віджети — це read-only представлення: вони не обробляють touch-події (крім тапу, який відкриває застосунок). Віджети не підтримують анімацію, відео, клавіатурне введення, скролінг або інтерактивні елементи. Кожен віджет — це статичний знімок даних на визначений момент часу, і спроба додати інтерактивність призведе до відхилення застосунку в App Store.
Кращі практики включають використання Widget Center для примусового оновлення, кешування даних на рівні TimelineProvider для швидкого відгуку та використання placeholder для початкового стану. Також важливо підтримувати кілька розмірів — користувач очікує, що віджет буде доступний як у small, так і в medium варіанті. Уникайте відображення неточних або застарілих даних — користувач запам'ятовує неправильну інформацію з віджета надовго.
| Що не можна | Чому |
|---|---|
| Анімація та відео | Віджети — статичні знімки; анімація розряджає батарею |
| Інтерактивність | WidgetKit не підтримує UI-елементи, крім посилання на застосунок |
| Скролінг | Фіксований розмір без прокрутки |
| Клавіатура | Введення тексту у віджеті неможливе |
| Живі дані | Дані оновлюються за розкладом Timeline, не в реальному часі |
| Кастомні розміри | Лише small, medium, large, accessory* фіксовані |
Часті запитання
Так, WidgetKit кроссплатформний. Одне й те саме Widget Extension може бути включене в iOS, iPadOS та macOS таргети з єдиним SwiftUI-кодом. Відмінності проявляються лише в підтримуваних Family — на Mac немає accessoryRectangular.
За розкладом Timeline. Розробник визначає, коли буде наступне оновлення — через хвилину або через добу. Система також може прискорювати оновлення для часто використовуваних віджетів.
Ні, WidgetKit не підтримує UIButton або будь-які інтерактивні елементи. Єдина дія — тап по віджету, який відкриває застосунок deep link.
Використовуйте WidgetCenter.shared.reloadAllTimelines() або reloadTimelines(ofKind:) для конкретного віджета. Виклик із застосунку негайно запитує новий Timeline у провайдера.
Мінімально — менше 1% заряду на день при типовому використанні. WidgetKit обмежує фонові оновлення та не тримає застосунок активним. Основний витрата — створення Timeline при першому додаванні.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.