Streaming is available in most browsers,
and in the Developer app.
-
What’s new in watchOS 26
Discover the new features in watchOS 26 and learn how to integrate them into your watchOS and iOS apps. Explore the ARM64 architecture, and dive into the new design system. We'll also share updates for widgets and insights on how to bring controls to Apple Watch.
Chapters
- 0:00 - Introduction
- 0:56 - Update for watchOS 26
- 3:48 - Bring apps to new places
- 9:44 - Be relevant and up-to-date
Resources
- Creating controls to perform actions across the system
- Increasing the visibility of widgets in Smart Stacks
- Making a configurable widget
- MapKit
- Migrating ClockKit complications to WidgetKit
- Workouts and activity rings
Related Videos
WWDC25
WWDC24
WWDC23
WWDC22
-
Search this video…
Hello and welcome. My name is Anne, and I’m happy to be with you today to share some of the great new features for watchOS 26 and tips on how you can use them in your apps. I’m going to introduce you to updates to watchOS 26, show you how you can take your watchOS and iOS apps to more places on Apple Watch, and share new ways to show timely and relevant content from your app.
Along the way, I’m going to be building an app to display wellness and recreational activities at nearby beaches, show the ocean conditions at any beach, and conveniently track mindful minutes at the beach, or wherever I am, when I’d rather be at the beach. Let's dive in and get started.
watchOS 26 features improvements from top to bottom, with a fresh new look all the way to a new system architecture. And there are a few things to know so your apps can get the most out of watchOS.
watchOS has been updated throughout the OS with the new design system, including changes to materials and controls, updates to app icons, and changes to system spaces like the watch face and Control Center.
Toolbar and control styles have been updated for watchOS 26. All apps built for watchOS 10 and later automatically use the new styles, so your app feels consistent with the rest of the system.
Run your app to verify the appearance of your interface.
If you have custom styles, audit them to ensure your user interface elements are legible with the new system style.
For more information about designing and updating apps, be sure to watch Meet Liquid Glass.
App icons also have a new appearance in iOS and watchOS 26.
Use Icon Composer to update your app icon.
Your updated iOS app icon appears in notifications forwarded from iPhone to Apple Watch.
And your updated Watch app icon appears in the app grid and list, and in notifications sent directly to Apple Watch.
To learn more about Icon Composer and all the new features for icons in apps, check out “Create icons with Icon Composer”. In addition to the new design system, watchOS supports a new system architecture. Apple Watch Series 9 and later, and Apple Watch Ultra 2 now use the arm64 architecture on watchOS 26.
In Xcode, use the Standard Architecture’s build setting on your Apple Watch targets. This configures your targets to build for all Apple Watch architectures.
Be aware of the differences in types on arm64, particularly when using Float, Int, and when doing pointer-based math.
And make sure to test both on the simulator and on devices.
Xcode has supported building Apple Watch apps for the arm64 architecture since Xcode 14.
The Apple Watch Simulator always uses the arm64 architecture on Apple Silicon.
And good news. If you’re already building with standard architectures, you’re already building for arm64. And if you’ve been using the simulator to test, you’re already testing with arm64. A new design system and a brand new architecture are just the start of this tour of watchOS 26. Let’s check out some new places where you can take your app.
Controls are available on Apple Watch starting in watchOS 26. People can place your controls in the Control Center, the Smart Stack, and use them with the Action button on Apple Watch Ultra.
Controls are built with WidgetKit and allow people to perform quick actions without opening your app or to launch your app to a specific view. Controls provide a symbol, title, tint color, and additional context to the system.
People can add the control to any of the supported system spaces, and the control is displayed contextually.
People can add the controls from your iPhone app to system spaces on Apple Watch, even if you don’t have a Watch app.
When the control is tapped on the Apple Watch, the action is performed on the companion iPhone. Since the action is performed on iPhone, controls whose actions foreground the iPhone app will not appear on Apple Watch.
If you have a Watch app, you can also build Apple Watch controls using the same API used to build controls for iOS. When the control is tapped, the action is performed on the Apple Watch.
The Smart Stack now supports Controls, Widgets, and Live Activities. With so many ways to show content in the Smart Stack, it can be hard to decide which one to choose.
It’s helpful to consider the primary purpose. Build a control when the primary purpose is to perform an action, like changing a setting in your app or turning on an internet-connected device.
Build a widget to display information throughout the day, for example to display weather information or upcoming events.
Build a Live Activity for events with a clear start and end, like the progress of a sports event or an airline flight.
To get started with controls and get more details, join Cliff for “Extend your app’s controls across the system”.
Some people may want to customize their widgets and controls from your app. On iOS, people can edit a widget by selecting from configurations that you provide to the system. Starting in watchOS 26, people can customize your widgets and controls in the same way.
Widgets can indicate that they are configurable instead of providing pre-configured recommendations. Here, I’m changing the configuration of my widget to see the calendar for Amelia Island. To make a widget configurable, return an empty array for recommendations to indicate that there are no pre-configured widgets and that a person can configure the widget in the watch face or Smart Stack.
If you have an existing widget that you’d like to make configurable, add an availability check for watchOS 26. Return an empty array to indicate that your widget is configurable in versions where it is supported.
For earlier versions, continue to return an array of app intent recommendations. People can configure controls as well. For example, in my beach app, I’d like to provide an additional configuration for my meditation timer control. I know people can’t always get to the beach, so I’d like an option for the app to play ocean sounds during the meditation. To make a control configurable, use an AppIntentControlConfiguration to describe the control, just like you do on iOS, and conform your value provider to AppIntentControlValueProvider. It’s not just controls coming to the Smart Stack in watchOS 26.
If your Watch app uses HealthKit to record workouts, it may be suggested in the Smart Stack based on a person’s routine.
They can tap on it to quickly get their workout started.
To ensure that your workout app is suggested appropriately, specify the correct HKWorkoutActivityType, record the accurate start and end time of workouts, and use an HKWorkoutRouteBuilder to add location data throughout the workout.
Speaking of taking your app to new places, there are many new features available for MapKit in watchOS 26. You can search for a nearby point of interest like a grocery store, get routes to locations using a transport type like driving, walking, or cycling, and show routes as an overlay on a map with SwiftUI, all using the same API you may already be familiar with from iOS. This is great for independent Watch apps that would like to find places nearby and show directions. Here, I’m showing the route to one of my favorite beaches.
To learn more about routes and local search, join Jeff in Meet MapKit for SwiftUI.
Between custom controls and Control Center, Workout app suggestions on the Watch Face, and new MapKit features, watchOS 26 introduces so many ways to take your experiences to new places on the system.
This tour of watchOS 26 has one more stop: a new way to create contextual and relevant experiences in the Smart Stack. You can show people the information and actions they want when it matters most, and keep that information up to date. watchOS 26 introduces a new framework: RelevanceKit. RelevanceKit helps show content just when someone wants it.
RelevanceKit has many relevant context types that allow you to suggest widgets in the Smart Stack based on contextual cues. These relevant contexts include date, sleep schedule, fitness information, and location. In watchOS 26, your widget can also be relevant at point-of-interest categories to indicate that your widget is relevant at any location for a type of place, like a grocery store, cafe, or even a beach. In my beach app, I’d like to show the current ocean conditions in the Smart Stack when someone is at the beach. Create a location RelevantContext for a MapKit point-of-interest category. This returns nil if the category is unsupported. Return WidgetRelevance with attributes for all the relevant contexts for the widget. In addition to RelevanceKit, watchOS 26 introduces a new widget configuration exclusively for the Smart Stack.
The new Relevant widget is powered by RelevanceKit and allows you to pick which views should appear from your widget. Views are suggested based on a particular RelevantContext, such as a point of interest or time of day. Relevant widgets appear exclusively in the Smart Stack, and multiple views may be suggested simultaneously. In watchOS 26, relevant widgets are being used to do some really cool things, like show multiple upcoming Calendar events, display a widget to quickly launch a recently edited note, and show the weather forecast for a person’s upcoming vacation destination. My Beach Events widget shows the activities scheduled throughout the day at a location, and I can improve it by making it a relevant widget.
This is a sample calendar for my beach events widget, and some of the events are happening at the same time. To build my existing Timeline widget, I need to create a single timeline of entries, but I have multiple events events overlapping. So my timeline includes entries that have multiple events to represent the overlapping times. When I compare my event calendar to my timeline at 9:30 this works great. I can display both the fundraiser and the meditation in a single view on two lines. But at 10 o’clock there are three events. When I try to put all three events in the widget, the view is truncated. I need to pick which two events to display. A relevant widget addresses this challenge. When multiple events are relevant, like around 10:00 AM, the system can suggest multiple cards in the Smart Stack, with one for each event. I’ll go through how to create a relevant widget for the beach events. To start, let’s quickly recap the anatomy of a widget.
The fundamental building block of a widget is an entry. The entry contains all the data you need to render the widget’s view.
Entries are created by the entry provider, which also advises WidgetKit when to update a widget’s display.
The configuration creates the entry provider and uses the entry and other information to produce a SwiftUI view.
When creating a timeline-based widget, these types are called TimelineEntry, AppIntentTimelineProvider, and AppIntentConfiguration.
Creating a relevant widget is similar to a timeline widget. The fundamental building block of a relevant widget is a RelevanceEntry.
These are created by the RelevanceEntriesProvider and supplied to the RelevanceConfiguration.
Let’s go through the steps to build a relevant widget, starting with the RelevanceEntry.
For my beach app, I’ll create a RelevanceEntry that contains the beach event, which has all the data needed to populate the widget’s view: the event’s location, title, and date. Next, I’ll implement the RelevanceEntriesProvider.
The relevance method tells the system when your widget is relevant. In it, I’ll create an array of WidgetRelevanceAttributes to associate the WidgetConfigurationIntents for the events at the beach to the RelevantContext with the cues about when the information is important. This is the date of the event for what’s happening at the beach. Then I’ll return the relevance with these attributes. When the widget is relevant, the system calls entry and provides the app with the WidgetConfigurationIntent that is relevant and some context information that includes the widget display size and whether the widget is being displayed as a preview.
The preview is displayed in the widget suggestions settings available from the Settings app or while editing the Smart Stack.
Return a preview entry with data to populate the settings view. I think Surfing at Playalinda is a great example to preview my widget.
Otherwise, use the information from the configuration, like my beach event, to create an entry that will populate the widget’s view.
While the widget is loading but hasn’t populated data yet, the system requests a placeholder entry from the provider. For example, if your widget needs to download new data to populate your widget, your entry method might not be able to return promptly.
Return a placeholder entry to indicate that the information is out of date or currently loading. In my widget, I’m returning an entry that will display a loading indicator in the view.
Lastly, I'll create the widget.
In the widget’s body, return a RelevanceConfiguration, using the provider, and a closure to create the widget’s view using the current RelevanceEntry.
Now the Smart Stack can suggest multiple cards for beach events when there are several upcoming events. My app still has a widget with a timeline to show events at the beach, and people can add that to their Smart Stack.
If someone has added my Timeline widget to their Smart Stack, the system will display two cards for the same event: one from the timeline widget the person added, and another that was suggested from the relevant widget. To prevent this duplication, associate the RelevanceConfiguration to the WidgetConfiguration for the timeline widget. This system will replace the timeline widget with the relevant widget cards when they are suggested.
This ensures that only one card displays for each event.
To associate the widgets, add the associatedKind modifier to the RelevanceConfiguration and pass it the widget kind for the timeline widget. So that's how you build a relevant widget. I have one more tip to ensure your widgets look great: Use previews. Previews allow you to visualize how your relevant widgets will appear in the Smart Stack without simulating the relevant conditions. I’ll give you a quick tour of three ways to preview your widgets for different use cases.
While you’re developing your widget’s view, use a preview with relevanceEntries to quickly check and fine-tune the appearance of your widget’s view across a range of sizes for different displays. Here I’m trying two events to see the view’s layout with different amounts of text. While you’re developing your entry method, use a preview with relevance to quickly check the creation of entries with specific WidgetConfigurationIntents. Here I’m creating the relevance with some sample configurations and verifying that the entries and views are being created correctly.
For a final check of a relevant widget, use a preview with the RelevanceProvider.
I’m providing a preview event store with five events to display in the previews so I can verify that different events are displayed beautifully on all display sizes. It’s great to be able to show people information that’s important to them at the right time. That information also needs to be up to date. I’ve got exciting news about another tool to keep widget data current.
Beginning in watchOS 26, you can send push updates to widgets using APNs. Widget push updates are supported for all widgets on all Apple platforms that support WidgetKit. To learn all about adding support for push updates to widgets, be sure to check out “What’s new in widgets” with Tanner. If you haven’t migrated your ClockKit complications to widgets because you needed complication push updates, now is the time! Join August for some tips to make the transition smoother in “Go further with Complications in WidgetKit”.
I hope you enjoy all the new features of watchOS.
Build and run your app on watchOS 26 to ensure that it looks great with the rest of the system and runs flawlessly on the arm64 architecture.
Try out your iOS controls on Apple Watch and add controls to your Watch app, especially if you have an independent Watch app.
Build relevant widgets where they fit in your app. and use push notifications to keep your widgets up-to-date. I love using your apps on my Apple Watch every day, whether I’m going for a walk, taking a trip, or going to the beach. Let’s keep exploring and keep going new places together with your apps.
-
-
6:53 - Make a widget configurable
// In the AppIntentTimelineProvider func recommendations() -> [AppIntentRecommendation<BeachConfigurationIntent>] { return [] }
-
7:06 - Support earlier versions of watchOS with a configurable widget
// In the AppIntentTimelineProvider func recommendations() -> [AppIntentRecommendation<BeachConfigurationIntent>] { if #available(watchOS 26, *) { // Return an empty array to allow configuration of the widget in watchOS 12+ return [] } else { // Return array of recommendations for preconfigured widgets before watchOS 12 return recommendedBeaches } }
-
7:46 - Use AppIntentControlConfiguration to make a control configurable
struct ConfigurableMeditationControl: ControlWidget { var body: some ControlWidgetConfiguration { AppIntentControlConfiguration( kind: WidgetKinds.configurableMeditationControl, provider: Provider() ) { value in // Provide the control's content } .displayName("Ocean Meditation") .description("Meditation with optional ocean sounds.") .promptsForUserConfiguration() } }
-
7:56 - Use AppIntentControlValueProvider for a configurable control
extension ConfigurableMeditationControl { struct Provider: AppIntentControlValueProvider { func previewValue(configuration: TimerConfiguration) -> Value { // Return the value to show in the add sheet } func currentValue(configuration: TimerConfiguration) async throws -> Value { // Return the control's value } } }
-
10:53 - Relevance for a point-of-interest category
func relevance() async -> WidgetRelevance<Void> { guard let context = RelevantContext.location(category: .beach) else { return WidgetRelevance<Void>([]) } return WidgetRelevance([WidgetRelevanceAttribute(context: context)]) }
-
14:37 - Implement the relevance method in the RelevanceEntriesProvider
struct BeachEventRelevanceProvider: RelevanceEntriesProvider { let store: BeachEventStore func relevance() async -> WidgetRelevance<BeachEventConfigurationIntent> { // Associate configuration intents with RelevantContexts let attributes = events.map { event in WidgetRelevanceAttribute( configuration: BeachEventConfigurationIntent(event: event), context: .date(interval: event.date, kind: .default) ) } return WidgetRelevance(attributes) } }
-
15:09 - Create a RelevanceEntry when the widget is relevant
struct BeachEventRelevanceProvider: RelevanceEntriesProvider { func relevance() async -> WidgetRelevance<BeachEventConfigurationIntent> { // Return relevance information for the widget } func entry( configuration: BeachEventConfigurationIntent, context: Context ) async throws -> BeachEventRelevanceEntry { if context.isPreview { return .previewEntry } return BeachEventRelevanceEntry( event: configuration.event ) } }
-
15:55 - Create a placeholder entry to display when the widget is loading
struct BeachEventRelevanceProvider: RelevanceEntriesProvider { func relevance() async -> WidgetRelevance<BeachEventConfigurationIntent> { // Return relevance information for the widget } func entry( configuration: BeachEventConfigurationIntent, context: Context ) async throws -> BeachEventRelevanceEntry { // Return the entry for the configuration } func placeholder(context: Context) -> BeachEventRelevanceEntry { BeachEventRelevanceEntry.placeholderEntry } }
-
16:27 - Use a RelevanceConfiguration to create a relevant widget
struct BeachEventWidget: Widget { private let model = BeachEventStore.shared var body: some WidgetConfiguration { RelevanceConfiguration kind: "BeachWidget provider: BeachEventRelevanceProvider(store: model) ) { entry in BeachWidgetView(entry: entry) } .configurationDisplayName("Beach Events") .description("Events at the beach") } }
-
17:31 - Use associatedKind to relate the relevant widget to the timeline widget
struct BeachEventWidget: Widget { private let model = BeachEventStore.shared var body: some WidgetConfiguration { RelevanceConfiguration kind: "BeachWidget provider: BeachEventRelevanceProvider(store: model) ) { entry in BeachWidgetView(entry: entry) } .configurationDisplayName("Beach Events") .description("Events at the beach") .associatedKind(WidgetKinds.beachEventsTimeline) } }
-
18:06 - Create a Preview with relevanceEntries
#Preview("Entries") { BeachEventWidget() } relevanceEntries: { BeachEventRelevanceEntry.previewShorebirds BeachEventRelevanceEntry.previewMeditation }
-
18:26 - Create a Preview with relevance
#Preview("Provider and Relevance") { BeachEventWidget() } relevanceProvider: { BeachEventRelevanceProvider(store: .preview) } relevance: { let configurations: [BeachEventConfigurationIntent] = [ .previewSurfing, .previewMeditation, .previewWalk ] let attributes = configurations.map { WidgetRelevanceAttribute( configuration: $0, context: .date($0.event.startDate, kind: .default) ) } return WidgetRelevance(attributes) }
-
18:47 - Create a Preview with a relevanceProvider
#Preview("Provider") { BeachEventWidget() } relevanceProvider: { BeachEventRelevanceProvider(store: .preview) }
-
-
- 0:00 - Introduction
watchOS 26 has new features and platform considerations.
- 0:56 - Update for watchOS 26
Explore the new design system on watchOS with updates to controls, app icons, and system spaces. Learn tips to support the arm64 architecture on watchOS 26.
- 3:48 - Bring apps to new places
Extend the presence of your app across watchOS. Controls help people to perform quick actions and can be added to the Control Center, Smart Stack, and Action button on Apple Watch Ultra. Controls are automatically available from iOS apps or can be built directly on watchOS. Apps that record workouts with HealthKit can be automatically suggested in the Smart Stack based on people’s routine. MapKit APIs from iOS are also available on watchOS 26, like finding directions between two places, or displaying routes as overlays.
- 9:44 - Be relevant and up-to-date
RelevanceKit powers a new way to show widgets in the Smart Stack when they’re the most relevant, based on criteria like date, sleep schedule, or location. Building a relevant widget has similar steps to building a timeline-based widget. Learn tips to build and test your relevant widget but using Previews.