WidgetKit — що це, фреймворк віджетів та SwiftUI

Автор: IT Sectr Опубліковано: 2026-06-16 Час читання: 9 хв

WidgetKit — це фреймворк Apple, представлений в iOS 14, який дозволяє розробникам розміщувати динамічні віджети на домашньому екрані iPhone та iPad, робочому столі Mac та циферблаті Apple Watch. Віджети відображають ключову інформацію без відкриття застосунку — прогноз погоди, курс валют, календар, кроки. За даними Apple Developer Documentation, 2026, WidgetKit обробляє до 2 мільярдів оновлень віджетів щодня в екосистемі Apple, що робить його одним із найбільш використовуваних фреймворків для відображення інформації на системних екранах.

Головне

  • WidgetKit — фреймворк для створення віджетів на iOS 14+, iPadOS 14+, macOS 11+ та watchOS 10+ з рендерингом через SwiftUI.
  • TimelineProvider — протокол, який визначає, коли та як часто віджет оновлює свій вміст на основі TimelineEntry.
  • WidgetFamily — три розміри (small, medium, large), кожен з яких розробник може налаштувати окремо.
  • WidgetConfiguration — точка входу у віджет, яка визначає тип конфігурації (Static, Intent, AppEntity) та сімейства розмірів.
  • Обмеження — віджети не анімовані, не підтримують відео, клавіатуру та скролінг всередині себе.

Що таке WidgetKit і як він працює?

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% заряду батареї на день при типовому використанні завдяки тому, що оновлення відбуваються за розкладом, а не в реальному часі.

Що відрізняє WidgetKit від старих Today Extensions

До iOS 14 віджети існували лише у вигляді Today View — панелі, доступної свайпом вліво від першого екрана. Today Extensions мали серйозні обмеження: вони були доступні лише на екрані «Сьогодні», вимагали відкриття застосунку для оновлення вмісту та мали обмежену підтримку розмірів. WidgetKit повністю замінив Today Extensions, надавши віджети на домашньому екрані, екрані блокування (iOS 16+) та робочому столі Mac.

  • Віджети на домашньому екрані, а не лише в Today View
  • Автономне оновлення через TimelineProvider, без відкриття застосунку
  • Три визначених розміри замість одного
  • Smart Rotate та Smart Stack — автоматична ротація віджетів системою
  • Єдиний API на SwiftUI для всіх платформ Apple

Архітектура WidgetKit: TimelineProvider та Entry

Архітектура WidgetKit будується на трьох ключових протоколах: TimelineProvider, TimelineEntry та Widget. TimelineEntry — це модель даних, що представляє стан віджета у конкретний момент часу. TimelineProvider створює масив таких записів (Timeline), вказуючи дату активації для кожного. Widget — точка входу, яка пов'язує провайдера з представленням SwiftUI.

Метод Timeline getTimeline викликається системою при першому додаванні віджета, а потім періодично — зазвичай кожні 1–6 годин залежно від типу провайдера. Timeline може містити записи на години або дні вперед, що дозволяє віджету працювати без виклику коду застосунку між оновленнями. Якщо необхідно терміново оновити віджет (наприклад, змінився курс валют), застосунок може викликати WidgetCenter.shared.reloadAllTimelines() примусово.

Базовий TimelineProvider

swift
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)
    }
}

Widget Family: small, medium, large

WidgetKit підтримує три розміри віджетів, кожен з яких має фіксовані пропорції. Small (170×170 pt на iPhone) відображає компактну інформацію — одне значення, іконку або короткий текст. Medium (364×170 pt) вдвічі ширший за small і підходить для відображення пари значень або міні-графіка. Large (364×382 pt) займає майже половину екрана по вертикалі та дозволяє відображати таблиці, списки або розгорнуті дані.

Розробник зобов'язаний підтримувати хоча б два розміри — Apple рекомендує small + medium. Large віджет потрібен лише якщо застосунок має достатньо вмісту для заповнення такого обсягу. Кожен розмір отримує власне SwiftUI View, яке WidgetKit рендерить на системному екрані. Важливо, що WidgetKit не підтримує кастомні розміри — лише три фіксованих, що гарантує єдність інтерфейсу.

Конфігурація розмірів через WidgetConfiguration

swift
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])
    }
}

Типи конфігурації віджетів: Static та Intent

WidgetKit пропонує два типи конфігурації — StaticConfiguration та IntentConfiguration. StaticConfiguration підходить для віджетів, які відображають однаковий вміст для всіх користувачів: курси валют, погода, календар. IntentConfiguration дозволяє користувачеві налаштовувати віджет при додаванні через систему інтентів Siri — наприклад, вибрати конкретне місто для погоди або конкретний тікер для курсу акцій.

IntentConfiguration використовує INWidgetIntent — підклас INIntent з SiriKit. Коли користувач додає віджет та вибирає параметри (наприклад, місто), система зберігає цей інтент і передає його в TimelineProvider при кожному оновленні. Провайдер отримує інтент у методі getTimeline та використовує його параметри для формування вмісту. IntentConfiguration — кращий спосіб для персоналізованих віджетів, оскільки він інтегрується з Siri та Shortcuts.

IntentConfiguration з вибором параметрів

swift
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)
        }
    }
}

Створення віджета на SwiftUI: покроковий приклад

Створення віджета починається з додавання Widget Extension Target в Xcode: File → New → Target → Widget Extension. Xcode автоматично генерує структуру з TimelineEntry, TimelineProvider та WidgetConfiguration. Розробнику залишається лише реалізувати SwiftUI View для відображення даних та налаштувати провайдера для коректного розкладу оновлень.

Нижче — повний приклад простого віджета для відображення поточного курсу біткоїна: Provider завантажує курс через URLSession та створює Timeline з оновленням щогодини. WidgetSwiftUIView відображає курс великим шрифтом та час останнього оновлення дрібним шрифтом.

swift
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+

З iOS 16 WidgetKit розширив підтримку на Екран блокування — екран блокування iPhone. Віджети екрана блокування бувають двох типів: inline (один рядок тексту під годинником) та rectangular (прямокутна область). На відміну від віджетів домашнього екрана, віджети екрана блокування оновлюються частіше — системний тригер дозволяє оновлювати їх кожні 15–30 хвилин для відображення актуальної інформації без розблокування телефону.

Віджети екрана блокування вимагають окремої конфігурації через WidgetConfiguration з accessoryFamilies: accessoryCircular, accessoryRectangular, accessoryInline. Ці сімейства мають суворі обмеження щодо розміру та вмісту — вони не підтримують зображення, анімацію та кастомні шрифти. Apple рекомендує використовувати лише текстову інформацію та системні іконки SF Symbols для віджетів екрана блокування.

  • accessoryCircular — компактний круглий віджет для місця під годинником
  • accessoryRectangular — прямокутний віджет для області над годинником
  • accessoryInline — однорядковий текст під часом, мінімальний розмір
  • Обмеження: лише текст, SF Symbols, градієнти; без зображень та відео

Кращі практики та обмеження WidgetKit

При розробці віджетів важливо враховувати обмеження WidgetKit. Віджети — це read-only представлення: вони не обробляють touch-події (крім тапу, який відкриває застосунок). Віджети не підтримують анімацію, відео, клавіатурне введення, скролінг або інтерактивні елементи. Кожен віджет — це статичний знімок даних на визначений момент часу, і спроба додати інтерактивність призведе до відхилення застосунку в App Store.

Кращі практики включають використання Widget Center для примусового оновлення, кешування даних на рівні TimelineProvider для швидкого відгуку та використання placeholder для початкового стану. Також важливо підтримувати кілька розмірів — користувач очікує, що віджет буде доступний як у small, так і в medium варіанті. Уникайте відображення неточних або застарілих даних — користувач запам'ятовує неправильну інформацію з віджета надовго.

Обмеження WidgetKit у таблиці

Що не можнаЧому
Анімація та відеоВіджети — статичні знімки; анімація розряджає батарею
ІнтерактивністьWidgetKit не підтримує UI-елементи, крім посилання на застосунок
СкролінгФіксований розмір без прокрутки
КлавіатураВведення тексту у віджеті неможливе
Живі даніДані оновлюються за розкладом Timeline, не в реальному часі
Кастомні розміриЛише small, medium, large, accessory* фіксовані

Часті запитання

Чи можна створити один віджет для iOS та macOS?

Так, WidgetKit кроссплатформний. Одне й те саме Widget Extension може бути включене в iOS, iPadOS та macOS таргети з єдиним SwiftUI-кодом. Відмінності проявляються лише в підтримуваних Family — на Mac немає accessoryRectangular.

Як часто WidgetKit оновлює віджети?

За розкладом Timeline. Розробник визначає, коли буде наступне оновлення — через хвилину або через добу. Система також може прискорювати оновлення для часто використовуваних віджетів.

Чи можна додати кнопку у віджет?

Ні, WidgetKit не підтримує UIButton або будь-які інтерактивні елементи. Єдина дія — тап по віджету, який відкриває застосунок deep link.

Як оновити віджет примусово із застосунку?

Використовуйте WidgetCenter.shared.reloadAllTimelines() або reloadTimelines(ofKind:) для конкретного віджета. Виклик із застосунку негайно запитує новий Timeline у провайдера.

Чи впливають віджети на час роботи батареї?

Мінімально — менше 1% заряду на день при типовому використанні. WidgetKit обмежує фонові оновлення та не тримає застосунок активним. Основний витрата — створення Timeline при першому додаванні.

Підсумки

  • WidgetKit — фреймворк Apple для віджетів на iOS 14+, iPadOS 14+, macOS 11+ та watchOS 10+, який використовує SwiftUI для відображення вмісту.
  • TimelineProvider керує розкладом оновлень через масив TimelineEntry, кожен з яких представляє стан віджета у визначений момент.
  • Widget Family включає три розміри — small, medium, large — та accessory-сімейства для екрана блокування iOS 16+.
  • StaticConfiguration підходить для однакового вмісту в усіх користувачів, IntentConfiguration — для персоналізованих віджетів з налаштуваннями.
  • Віджети статичні — без анімації, інтерактивності, скролінгу та відео; лише read-only відображення даних.
  • Віджети екрана блокування (iOS 16+) представлені accessoryCircular, accessoryRectangular та accessoryInline з обмеженнями на вміст.
  • Примусове оновлення через WidgetCenter.shared.reloadAllTimelines() дозволяє негайно запросити новий Timeline.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також