-
Nouveautés dans les widgets
WidgetKit optimise votre app grâce à des mises à jour des widgets, des Activités en direct et des commandes. Découvrez comment intégrer vos widgets à visionOS, les utiliser en voiture avec CarPlay et les sublimer avec des modes de rendu accentués. Découvrez également comment les widgets pertinents peuvent apparaître dans le Défilement intelligent sur watchOS, et comment les notifications push peuvent maintenir vos widgets à jour.
Chapitres
- 0:00 - Introduction
- 1:03 - Nouveaux emplacements des widgets
- 15:31 - Widgets pertinents
- 18:12 - Mises à jour des widgets via des notifications push
Ressources
- Updating widgets with WidgetKit push notifications
- Updating your widgets for visionOS
- Optimizing your widget for accented rendering mode and Liquid Glass
- RelevanceKit
- Increasing the visibility of widgets in Smart Stacks
Vidéos connexes
WWDC25
- Boostez les performances de votre app pour CarPlay
- Concevez des widgets pour visionOS
- Nouveautés dans watchOS 26
WWDC24
WWDC23
WWDC20
-
Rechercher dans cette vidéo…
-
-
2:44 - Observe .widgetRenderingMode
struct MostFrequentBeverageWidgetView: View { @Environment(\.widgetRenderingMode) var renderingMode var entry: Entry var body: some View { ZStack { if renderingMode == .fullColor { Image(entry.beverageImage) .resizable() .aspectRatio(contentMode: .fill) LinearGradient(gradient: Gradient(colors: [.clear, .clear, .black.opacity(0.8)]), startPoint: .top, endPoint: .bottom) } VStack { if renderingMode == .accented { Image(entry.beverageImage) .resizable() .widgetAccentedRenderingMode(.desaturated) .aspectRatio(contentMode: .fill) } BeverageTextView() } } } } -
6:08 - visionOS Widget Configuration
struct CaffeineTrackerWidget: Widget { var body: some WidgetConfiguration { StaticConfiguration( kind: "BaristaWidget", provider: Provider() ) { entry in CaffeineTrackerWidgetView(entry: entry) } .configurationDisplayName("Caffeine Tracker") .description("A widget tracking your caffeine intake during the day.") .supportedMountingStyles([.elevated]) .widgetTexture(.paper) .supportedFamilies([.systemExtraLargePortrait]) } } -
8:56 - LevelOfDetail - CaffeineTrackerWidgetView
struct CaffeineTrackerWidgetView : View { @Environment(\.levelOfDetail) var levelOfDetail var entry: CaffeineLogEntry var body: some View { VStack(alignment: .leading) { TotalCaffeineView(entry: entry) if let log = entry.log { LastDrinkView(log: log) } if levelOfDetail == .default { LogDrinkView() } } } } -
9:46 - LevelOfDetail - TotalCaffeineView
struct TotalCaffeineView: View { @Environment(\.levelOfDetail) var levelOfDetail let entry: CaffeineLogEntry var body: some View { VStack { Text("Total Caffeine") .font(.caption) Text(totalCaffeine.formatted()) .font(caffeineFont) } } var caffeineFont: Font { if levelOfDetail == .simplified { .largeTitle } else { .title } } var totalCaffeine: Measurement<UnitMass> { entry.totalCaffeine } } -
11:49 - Add .supplementalActivityFamilies
struct ShopOrderLiveActivity: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: Attributes.self) { context in ActivityView(context: context) } dynamicIsland: { context in DynamicIsland { DynamicIslandExpandedRegion(.leading) { ExpandedView(context: context) } } compactLeading: { LeadingView(context: context) } compactTrailing: { TrailingView(context: context) } minimal: { MinimalView(context: context) } } .supplementalActivityFamilies([.small]) } } -
12:27 - Add .activityFamily
struct ActivityView: View { @Environment(\.activityFamily) var activityFamily var context: ActivityViewContext<Attributes> var body: some View { switch activityFamily { case .small: ShopOrderSmallView(context: context) default: ShopOrderView(context: context) } } } -
16:20 - Define relevance widget with RelevanceConfiguration
struct HappyHourRelevanceWidget: Widget { var body: some WidgetConfiguration { RelevanceConfiguration( kind: "HappyHour", provider: Provider() ) { entry in WidgetView(entry: entry) } } } -
16:41 - Implement RelevanceEntriesProvider
struct Provider: RelevanceEntriesProvider { func placeholder(context: Context) -> Entry { Entry() } func relevance() async -> WidgetRelevance<Configuration> { let configs = await fetchConfigs() var attributes: [WidgetRelevanceAttribute<Configuration>] = [] for config in configs { attributes.append(WidgetRelevanceAttribute( configuration: config, context: .date(interval: config.interval, kind: .default))) } return WidgetRelevance(attributes) } func entry(configuration: Configuration, context: RelevanceEntriesProviderContext) async throws -> Entry { Entry(shop: configuration.shop, timeRange: configuration.timeRange) } } -
21:13 - Handle push token and widget configuration changes
struct CaffeineTrackerPushHandler: WidgetPushHandler { func pushTokenDidChange(_ pushInfo: WidgetPushInfo, widgets: [WidgetInfo]) { // Send push token and subscription info to server } } -
21:30 - Add pushHandler to WidgetConfiguration
struct CaffeineTrackerWidget: Widget { var body: some WidgetConfiguration { StaticConfiguration( kind: Constants.widgetKind, provider: Provider() ) { entry in CaffeineTrackerWidgetView(entry: entry) } .configurationDisplayName("Caffeine Tracker") .pushHandler(CaffeineTrackerPushHandler.self) } } -
22:29 - Push Notification Request Body
{ "aps": { "content-changed": true } }
-
-
- 0:00 - Introduction
Découvrez les nouveautés de WidgetKit, dont de nouveaux moyens d'intégrer votre app au système, d'afficher du contenu pertinent dans le défilement intelligent, et de garder vos widgets à jour.
- 1:03 - Nouveaux emplacements des widgets
Les widgets proposent de nouveaux styles et apparaissent dans plus d'endroits. Consultez les conseils pour améliorer l'esthétique des widgets grâce au mode de rendu accentué. Les widgets sont désormais disponibles sur davantage de plateformes, dont visionOS 26 et CarPlay. Sur visionOS 26, les widgets peuvent être ajoutés aux pièces et épinglés sur des surfaces. Ils peuvent être personnalisés selon les styles de montage, textures et niveaux de détail en fonction de la distance. CarPlay et macOS 26 prennent désormais en charge les Activités en direct. Des commandes sont disponibles sur macOS Tahoe et watchOS 26.
- 15:31 - Widgets pertinents
Les widgets pertinents apparaissent dans le défilement intelligent sur watchOS 26 en fonction de la routine, de la localisation, et d'autres critères utilisateur. Plusieurs instances peuvent apparaître simultanément dans le défilement intelligent, par exemple pour des événements de calendrier qui se chevauchent ou des happy hours. Créez des widgets pertinents en spécifiant quand ils sont les plus utiles : moment précis, type de lieu, etc.
- 18:12 - Mises à jour des widgets via des notifications push
Sur toutes les plateformes WidgetKit, les widgets peuvent maintenant recevoir des mises à jour via APNS. Plusieurs outils sont disponibles pour maintenir les widgets à jour ; le choix dépend du mode de mise à jour des données. Utilisez les calendriers pour les mises à jour régulières des données. Pour des changements liés à l'interaction dans l'app, utilisez reloadAllTimelines. Pour la synchronisation entre appareils ou les changements de données externes (ex. serveur), utilisez les mises à jour push pour widgets. Les mises à jour push pour les widgets permettent d'actualiser le contenu des widgets, mais elles ne remplacent pas directement d'autres expériences de notification. Déterminez si une Notification Utilisateur, une Activité en direct ou un widget est le choix le plus pertinent selon chaque usage.