-
Novidades dos widgets
O WidgetKit aprimora seu app com atualizações nos widgets, nas Atividades ao Vivo e nos controles. Saiba como incorporar seus widgets ao visionOS, adicioná-los ao CarPlay e deixá-los mais bonitos com os modos de renderização acentuados. Além disso, descubra como widgets relevantes podem aparecer no Conjunto Inteligente no watchOS e como as notificações por push podem ser usadas para manter seus widgets atualizados.
Capítulos
- 0:00 - Introdução
- 1:03 - Widgets em novos lugares
- 15:31 - Widgets de relevância
- 18:12 - Atualizações de widgets por push
Recursos
- 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
Vídeos relacionados
WWDC25
WWDC24
WWDC23
WWDC20
-
Buscar neste vídeo...
-
-
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 - Introdução
Saiba mais sobre as atualizações do WidgetKit, incluindo novas formas de incorporar o app ao sistema, mostrar conteúdo relevante no Conjunto Inteligente e manter seu app atualizado.
- 1:03 - Widgets em novos lugares
Os widgets têm novas opções de estilo e estão disponíveis em novos lugares. Confira dicas para deixar seus widgets ainda mais bonitos usando o modo de renderização com destaque. Os widgets estão disponíveis em mais lugares, incluindo o visionOS 26 e o CarPlay. No visionOS 26, eles podem ser adicionados aos ambientes e fixados a superfícies. Também podem ser personalizados para incluir compatibilidade com diferentes estilos de montagem, texturas e níveis de detalhes com base na proximidade. O CarPlay e o macOS 26 agora são compatíveis com Atividades ao Vivo. Os controles estão disponíveis no macOS Tahoe e no watchOS 26.
- 15:31 - Widgets de relevância
Os widgets mais relevantes aparecem no Conjunto Inteligente do watchOS 26 com base na rotina e na localização das pessoas e muito mais. Eles só são exibidos no Conjunto Inteligente quando são relevantes, e várias instâncias podem aparecer ao mesmo tempo, como no caso de eventos de calendário sobrepostos ou happy hours. Se quiser usar esse recurso, especifique em que situações seus widgets são mais relevantes, como em um determinado horário ou tipo de local.
- 18:12 - Atualizações de widgets por push
Agora os widgets de todas as plataformas do WidgetKit podem ser atualizados com atualizações por push no APNS. Existem várias ferramentas para manter os widgets atualizados, e a melhor opção para cada caso depende de como os dados do seu widget são atualizados. É útil ter cronogramas para atualizar os dados regularmente. Para as alterações impulsionadas pela interação com o app, é preciso chamar o método reloadAllTimelines. Para sincronização entre dispositivos ou alterações de dados externos, como de um servidor, use atualizações por push. Elas ajudam a manter os widgets mais atualizados, mas não substituem outras experiências de notificação. Considere se uma Notificação de Usuário, uma Atividade ao Vivo ou um widget é melhor para cada caso de uso.