Powierzchnia widżetów iOS 26: jeden App Intent, wiele miejsc
Przez lata widżet był migawką. System renderował widok na osi czasu, użytkownik na niego patrzył, a każde dotknięcie otwierało aplikację. Ten model odszedł w przeszłość. Od iOS 17 widżet może zawierać przyciski i przełączniki, które uruchamiają kod bez otwierania czegokolwiek, a kodem, który uruchamiają, jest App Intent1. To samo dotyczy elementów sterujących w Centrum sterowania oraz przycisków wewnątrz Live Activity. Gdy się to dostrzeże, powierzchnia widżetów iOS 26 przestaje wyglądać jak trzy oddzielne API, a zaczyna jak jedna: zbiór miejsc, w których system wyrenderuje wasze App Intents, z których każde dysponuje inną przestrzenią, a pod spodem ma tę samą instalację.
To przeformułowanie jest sednem całego tekstu. Wystarczy raz nauczyć się App Intent, by rozświetlić ekran główny, ekran blokady, Centrum sterowania, przycisk akcji, Dynamic Island oraz (znów ten sam intent) Siri i Apple Intelligence. Napiszcie trzy rozłączne funkcje, a wykonacie czterokrotnie więcej pracy dla gorszego rezultatu.
W skrócie
- Interaktywne widżety (iOS 17+): wystarczy umieścić
Button(intent:)lubToggle(isOn:intent:)w widoku widżetu; system uruchamia metodęperform()danego App Intent w rozszerzeniu widżetu, poza aplikacją, a następnie odświeża oś czasu1. - Elementy sterujące Centrum sterowania (iOS 18+):
ControlWidgetzbudowany zControlWidgetButtonlubControlWidgetToggle, oparty na tych samych App Intents, pojawia się w Centrum sterowania, na ekranie blokady i na przycisku akcji2. - Live Activities (ActivityKit):
ActivityAttributeswraz zActivityConfigurationnapędzają ekran blokady i Dynamic Island; aktualizacje sterowane z serwera przychodzą przez powiadomienia push, a przyciski w środku to także App Intents3. - iOS 26 dodaje warstwę renderowania, nie model: widżety przejmują prezentację w stylu Liquid Glass i akcentowane tryby renderowania, lecz architektura, w której App Intents pełnią rolę powierzchni, pozostaje niezmieniona względem iOS 184.
- Fakt, który to wszystko spaja: przycisk widżetu, element sterujący, fraza Siri i akcja Apple Intelligence mogą być tym samym App Intent. Zaprojektujcie daną możliwość raz.
Interaktywne widżety: przycisk, który nie otwiera aplikacji
Mechanizm jest niewielki i wart precyzyjnego ujęcia. Do widoku widżetu dodaje się Button lub Toggle z SwiftUI, ale zamiast domknięcia z akcją przekazuje się App Intent1:
struct WaterWidgetView: View {
let logged: Int
var body: some View {
VStack {
Text("\(logged) glasses")
Button(intent: LogWaterIntent()) {
Label("Add", systemImage: "plus")
}
}
}
}
Gdy użytkownik dotyka, system uruchamia LogWaterIntent.perform() wewnątrz rozszerzenia widżetu. Aplikacja się nie uruchamia. Intent wykonuje swoją pracę (zapis do współdzielonego magazynu, aktualizacja licznika), a oś czasu widżetu odświeża się, aby pokazać wynik.
Toggle działa tak samo, za pośrednictwem SetValueIntent, który otrzymuje nową wartość włącz/wyłącz ustawioną właśnie przez użytkownika:
struct ToggleReminderIntent: SetValueIntent {
static let title: LocalizedStringResource = "Toggle Reminder"
@Parameter(title: "Enabled")
var value: Bool
func perform() async throws -> some IntentResult {
ReminderStore.shared.enabled = value
return .result()
}
}
Widżet wiąże Toggle(isOn: store.enabled, intent: ToggleReminderIntent()), system ustawia value na nowy stan, uruchamia perform() i odświeża widok. Ten sam kształt co przycisk, jeden parametr więcej1.
To, co można tu zrobić, określają dwa ograniczenia, a oba łatwo naruszyć. Po pierwsze, perform() działa w ograniczonym środowisku rozszerzenia widżetu, z ciasnym budżetem wykonania; służy do szybkiej zmiany stanu, a nie do przesyłania danych przez sieć czy ciężkich obliczeń. Po drugie, widżet odzwierciedla stan — nie animuje dowolnego interfejsu. Zmieniacie dane, a oś czasu renderuje się ponownie; nie uruchamiacie własnego przejścia. Zaprojektujcie interakcję jako „zmień wartość, pokaż nową wartość”, a zadziała. Sięgnijcie po więcej, a system będzie z wami walczył.
Elementy sterujące Centrum sterowania: ten sam intent, inny pokój
iOS 18 otworzył Centrum sterowania, ekran blokady i przycisk akcji na elementy sterujące innych firm, a API jest celowo zbieżne z tym dla widżetów2. Element sterujący to ControlWidget, a jego ciałem jest ControlWidgetButton lub ControlWidgetToggle podłączony do App Intent:
struct LogWaterControl: ControlWidget {
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(kind: "com.example.logWater") {
ControlWidgetButton(action: LogWaterIntent()) {
Label("Log Water", systemImage: "drop.fill")
}
}
}
}
Jeśli LogWaterIntent napędza już wasz interaktywny widżet, element sterujący kosztuje niemal nic: ten sam intent, nowe opakowanie. To właśnie moment, w którym architektura zaczyna się opłacać. Element sterujący nie jest drugą implementacją funkcji; jest drugim punktem zamontowania tej, którą już napisaliście. Przełącznikowy element sterujący korzysta z SetValueIntent dokładnie tak, jak robi to przełącznik widżetu, więc możliwość typu „wycisz”, „rozpocznij sesję” czy „przełącz tryb ciemny”, zbudowana raz, pojawia się w Centrum sterowania, na ekranie blokady i na przycisku akcji bez nowej logiki2.
Live Activities: powierzchnia, która aktualizuje się sama
Live Activities to trzecie z tych miejsc — i to z największą liczbą ruchomych części. Typ ActivityAttributes definiuje treść statyczną i dynamiczną, ActivityConfiguration renderuje prezentację na ekranie blokady oraz obszary Dynamic Island, a ActivityKit rozpoczyna, aktualizuje i kończy aktywność3. Przyciski wewnątrz Live Activity to, ponownie, App Intents, więc element „pauza” czy „następny” w Dynamic Island uruchamia ten sam rodzaj intentu, co przycisk widżetu.
Tym, co czyni z Live Activities odrębną dyscyplinę, jest ścieżka aktualizacji. Licznik czasu, który aktualizujecie lokalnie, jest prosty. Aktywność sterowana zdarzeniami zachodzącymi na serwerze (przesyłka w ruchu, zmieniający się wynik meczu) aktualizuje się przez powiadomienia push: rejestrujecie się w pushTokenUpdates, wysyłacie z zaplecza ładunki push ActivityKit, a system aktualizuje ekran blokady i Dynamic Island bez działania waszej aplikacji w ogóle3. To jest naprawdę potężne i naprawdę łatwe do zepsucia, bo poprawność waszej aktywności zależy teraz od kontraktu z serwerem, niezawodności push i polityki dat ważności, a nie tylko od lokalnego kodu.
Co iOS 26 faktycznie zmienił
Nagłówkiem dla widżetów iOS 26 jest prezentacja, a nie architektura. Widżety przejmują materiał Liquid Glass i zyskują akcentowane tryby renderowania, dzięki czemu pasują do nowego języka projektowania systemu i poprawnie przyjmują barwę w kontekstach, w których system zmienia kolorystykę treści4. Ma to znaczenie dla tego, jak widżet wygląda na ekranie głównym, ekranie blokady i w trybie StandBy, i jest warte oddzielnego przeglądu projektowego. Nie zmienia to natomiast działania interaktywności. Jeśli zbudowaliście interaktywne widżety i elementy sterujące na iOS 18, ruch w iOS 26 to odświeżenie wizualne, a nie przepisanie od nowa. Twierdzenia, jakoby iOS 26 „wprowadził” interaktywne widżety, traktujcie z podejrzliwością; interaktywność pojawiła się w iOS 17, elementy sterujące w iOS 18, a iOS 26 sprawił, że wyglądają jak reszta systemu.
Implikacja projektowa Liquid Glass jest jednak realna. Widżet to treść, którą system komponuje na tle tapety i załamuje przez szklaną chromę, więc obowiązują te same zasady, co dla Liquid Glass w aplikacji: uszanujcie podział na warstwę funkcjonalną i warstwę treści oraz nie walczcie z materiałem ciężkimi, własnymi tłami, których szkło nie potrafi odczytać.
Architektura, wyłożona wprost
Oto model wart zapamiętania. App Intent to nazwana, typowana, opisana możliwość. iOS daje wam rosnący zbiór miejsc, w których można tę możliwość zamontować:
ButtonlubTogglewewnątrz widżetu.ControlWidgetw Centrum sterowania, na ekranie blokady i na przycisku akcji.- Przycisk wewnątrz Live Activity oraz jej Dynamic Island.
- Fraza Siri i akcja Shortcuts.
- Akcja, którą Apple Intelligence może wywołać w imieniu użytkownika5.
Każde z tych miejsc to ten sam typ AppIntent z metodą perform(). Praca tkwi w dobrym zaprojektowaniu tej możliwości: jasna nazwa, typowane parametry, szybkie i idempotentne perform() oraz sensowny wynik. Zróbcie to raz, a powierzchnie staną się opakowaniami. To ten sam argument, który stawiałem w odniesieniu do App Intents jako prawdziwego API do waszej aplikacji oraz do trzech powierzchni, które aplikacja iOS dziś udostępnia: powierzchnia widżetów nie jest funkcją, którą budujecie — jest miejscem, w którym wasze możliwości pojawiają się, gdy już istnieją.
Kiedy nie warto się trudzić
Powierzchnia widżetów nagradza aplikacje z prawdziwym, dostępnym na pierwszy rzut oka stanem i szybkimi akcjami: tracker, licznik czasu, przełącznik, element sterujący odtwarzaniem. Nie nagradza wszystkiego.
- Brak stanu na pierwszy rzut oka — brak widżetu. Jeśli wasza aplikacja nie ma nic wartego pokazania bez jej otwierania, widżet jest dekoracją, która kosztuje was utrzymanie i dodatkowy cel rozszerzenia.
- Ciężkie lub wolne akcje nie należą tu do
perform(). Środowisko wykonawcze widżetów i elementów sterujących jest ograniczone. Jeśli akcja wymaga realnego czasu lub realnych obliczeń, przycisk powinien otworzyć aplikację w przygotowanym stanie, a nie udawać, że wykonuje pracę w rozszerzeniu. - Live Activity dla czegoś, co nie jest na żywo. Live Activities służą do zdarzeń ograniczonych w czasie i aktywnie się zmieniających. Używanie ich jako trwałej plakietki statusu to błędny odczyt powierzchni i szybka droga na czarną listę systemu w kwestii budżetu aktywności.
Umiejętność nie polega na nauczeniu się trzech API. Polega na projektowaniu App Intents wartych zamontowania, a następnie montowaniu ich tam, gdzie użytkownik już jest: na ekranie głównym, który sprawdza, w Centrum sterowania, do którego przesuwa palcem, w Dynamic Island, które już mu coś pokazuje. Zbudujcie daną możliwość raz, z wyczuciem, a iOS poda wam powierzchnie za darmo.
FAQ
Czy iOS 26 wprowadził interaktywne widżety?
Nie. Interaktywne widżety pojawiły się w iOS 17, a elementy sterujące Centrum sterowania w iOS 18; iOS 26 sprawił, że przejęły materiał Liquid Glass i akcentowane renderowanie, dzięki czemu pasują do języka projektowania systemu4. Twierdzenia, jakoby iOS 26 „wprowadził” interaktywne widżety, traktujcie z podejrzliwością: zmiana w iOS 26 to odświeżenie wizualne, a nie przepisanie od nowa.
Jak przycisk wewnątrz widżetu iOS faktycznie wykonuje pracę?
Przycisk uruchamia App Intent. Button lub Toggle w widżecie wywołuje nazwany, typowany AppIntent z metodą perform(), więc widżet działa bez otwierania aplikacji. Ten sam intent napędza element sterujący Centrum sterowania, przycisk Live Activity, frazę Siri i akcję Shortcuts5.
Co właściwie zmieniło się dla widżetów w iOS 26?
Prezentacja, nie architektura. Widżety przejmują Liquid Glass i zyskują akcentowane tryby renderowania, dzięki czemu poprawnie przyjmują barwę na ekranie głównym, ekranie blokady i w trybie StandBy4. Interaktywność działa dokładnie tak jak na iOS 18, więc istniejący interaktywny widżet potrzebuje przeglądu projektowego, a nie przepisania od nowa.
Jak Live Activities aktualizują się, gdy aplikacja nie działa?
Przez powiadomienia push. Rejestrujecie się w pushTokenUpdates, wysyłacie z zaplecza ładunki push ActivityKit, a system aktualizuje ekran blokady i Dynamic Island bez działania waszej aplikacji3. Sprawia to, że poprawność aktywności zależy od kontraktu z serwerem, niezawodności push i polityki dat ważności, a nie tylko od lokalnego kodu.
Gdzie może pojawić się pojedynczy App Intent?
Ten sam typ AppIntent montuje się w widżetowym Button/Toggle, w ControlWidget w Centrum sterowania / na ekranie blokady / na przycisku akcji, w Live Activity i jej Dynamic Island, we frazie Siri, w akcji Shortcuts oraz jako akcja, którą może wywołać Apple Intelligence5. Zaprojektujcie daną możliwość raz, a powierzchnie staną się opakowaniami.
Kiedy nie powinienem budować widżetu ani Live Activity?
Pomińcie widżet, gdy aplikacja nie ma stanu wartego pokazania na pierwszy rzut oka bez jej otwierania. Trzymajcie ciężkie lub wolne akcje z dala od perform() w ograniczonym środowisku widżetu; zamiast tego otwierajcie aplikację w przygotowanym stanie. I nie używajcie Live Activity jako trwałej plakietki statusu; służą do zdarzeń ograniczonych w czasie i aktywnie się zmieniających, a niewłaściwe użycie przepala wasz budżet aktywności.
-
Apple Developer, “Adding interactivity to widgets and Live Activities”. Interaktywne widżety (iOS 17+) korzystają z
Button(intent:)iToggle(isOn:intent:)z SwiftUI, opartych naAppIntent(lubSetValueIntentdla przełączników); metodaperform()intentu działa w rozszerzeniu widżetu bez uruchamiania aplikacji, a oś czasu odświeża się, by odzwierciedlić wynik. ↩↩↩↩ -
Apple Developer, “Creating controls to perform actions across the system” oraz protokół
ControlWidget. Elementy sterujące (iOS 18+) są zbudowane zControlWidgetButtoniControlWidgetTogglepodłączonych do App Intents i pojawiają się w Centrum sterowania, na ekranie blokady i na przycisku akcji. ↩↩↩ -
Apple Developer, “ActivityKit” oraz “Displaying live data with Live Activities”.
ActivityAttributesiActivityConfigurationdefiniują oraz renderują ekran blokady i Dynamic Island; ActivityKit rozpoczyna, aktualizuje i kończy aktywności, a aktualizacje sterowane z serwera korzystają z push przezpushTokenUpdates. ↩↩↩↩ -
Renderowanie widżetów w iOS 26: widżety przejmują materiał Liquid Glass i akcentowany tryb renderowania, sterowane przez
WidgetRenderingModeoraz wartość środowiskową\.widgetRenderingMode. Model interaktywności (App Intents w widżetach i elementach sterujących) pozostaje niezmieniony względem iOS 17 (widżety) i iOS 18 (elementy sterujące). Apple, “WWDC 2025: the new software design” oraz dokumentacja WidgetKit. ↩↩↩↩ -
Apple Developer, “App Intents”. Ten sam typ
AppIntentjest jednostką, którą system udostępnia przez Siri, Shortcuts, Spotlight, powierzchnie widżetów i elementów sterujących oraz Apple Intelligence. Analiza autora dotycząca modelu wielopowierzchniowego: App Intents to nowe API Apple do waszej aplikacji, App Intents 2 i dodatki w iOS 26 oraz trzy powierzchnie aplikacji iOS. ↩↩↩