Highlight
watchOS 26 では Controls、構成可能な Widget、
WidgetRelevanceベースの関連性シグナルが開発者に開放されます。あわせて Apple Watch Series 9 以降の機種が arm64 アーキテクチャへ移行します。
主要内容
これまで Apple Watch アプリを開発する際にもっとも悩ましかったのは、ユーザーが自らアプリを起動しなければ機能を使えないという点でした。文字盤のスペースは限られており、複雑な機能は小さな画面では動かしにくい。結果として、多くの iPhone アプリは Apple Watch 上ではアイコンだけが残り、何度かタップされたあとは二度と開かれない、という状態になりがちです。
watchOS 26 はこの導線を打開するために、3 つの変更を同時に投入してきました。1 つ目は、Controls が Apple Watch にやってくること(04:04)。Control Center や Smart Stack に配置できるほか、Apple Watch Ultra の Action ボタンに割り当てて、ワンタップでアクションを起動できます。2 つ目は、Widget が構成可能になったこと(06:53)。同じコードベースで、ユーザー自身に表示内容を選んでもらえるようになりました。3 つ目は、関連性 API のアップデートです。WidgetRelevance と RelevanceEntriesProvider を通じて、「どのような場面で自分を Smart Stack の上位に押し上げるべきか」をシステムに伝えられます。たとえば現在地がビーチ付近に入ったとき、あるいは特定のイベント開始時刻が近づいたときなどです(10:53、14:37)。
足回りも刷新されています。Apple Watch Series 9 以降の機種は、watchOS 26 で arm64 アーキテクチャへ移行しました(02:46)。Xcode 14 から arm64 watchOS アプリのビルドはサポートされており、Apple Silicon Mac 上のシミュレータも以前から arm64 で動作していたため、多くのプロジェクトでは “Standard Architectures” を有効にするだけで対応できます。ただし Float / Int / ポインタ演算の挙動が arm64 で変わる点には注意が必要です。シミュレータと実機の両方で一通り動作確認しておくとよいでしょう。
詳細
Widget を構成可能にするのは、今回の watchOS でもっともストレートな「コードの変更」です。AppIntentTimelineProvider で空配列を返すだけで、ユーザーに Widget の内容を構成してもらえるようになります。
// In the AppIntentTimelineProvider
func recommendations() -> [AppIntentRecommendation<BeachConfigurationIntent>] {
return []
}
ポイント:
recommendations()はAppIntentTimelineProviderプロトコルのメソッドで、システムにどんなプリセット構成があるかを伝えるためのものです。[]を返すと「プリセットを提供しない」ことを意味し、ユーザーが構成画面に進んでパラメータを自分で選ぶ流れになります。- ジェネリクス引数の
BeachConfigurationIntentは自分で定義したAppIntentで、Widget の構成可能なフィールドを担います。
Widget が古い OS との互換性を保つ必要がある場合は、#available で分岐すれば十分です(07:06)。
// 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
}
}
ポイント:
- watchOS 26 ではユーザーに構成を任せ、旧 OS では従来どおりプリセット一覧を返すことで、構成不可のときに空の Widget が出てしまう事態を避けられます。
recommendedBeachesは自分で管理するプリセット配列で、型は[AppIntentRecommendation<BeachConfigurationIntent>]です。
Control も構成可能な形にできます(07:46)。
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()
}
}
ポイント:
ControlWidgetはコントロールの型で、AppIntentControlConfigurationが Control とAppIntentを結びつけます。kindは Control の安定した識別子です。クロスプラットフォームで実装する場合は、iOS と watchOS で同じ定数を共有することを推奨します。.promptsForUserConfiguration()を付けると、Control をシステムに追加した瞬間に構成画面が開きます。「とりあえず置いてからあとで設定する」というステップを踏まずに済みます。
関連性シグナルは、Widget を Smart Stack の上位に押し上げるための鍵となります。位置情報ベースの関連性がもっとも単純です(10:53)。
func relevance() async -> WidgetRelevance<Void> {
guard let context = RelevantContext.location(category: .beach) else {
return WidgetRelevance<Void>([])
}
return WidgetRelevance([WidgetRelevanceAttribute(context: context)])
}
ポイント:
RelevantContext.location(category:)は、ビーチやジムといったセマンティックな場所のシナリオを記述するもので、現在の状況がそれに該当するかはシステムが判定します。WidgetRelevanceAttributeはコンテキストをシステムが読み取れる関連性属性へとパッケージングします。- 空配列を返すのは「現時点では関連性を申請しない」という意思表示であり、Smart Stack で能動的に表示されることはありません。
Widget が構成可能な場合は、各構成インスタンスごとに関連性を付与する必要があります(14:37)。
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)
}
}
ポイント:
RelevanceEntriesProviderを使うと、複数の構成インスタンスごとに個別の関連性を宣言できます。.date(interval:kind:)は関連性のウィンドウを特定の時間区間に紐づけるもので、イベントが近づくとシステムが自動で優先度を引き上げます。events.mapでデータソースをシステムが認識できる属性配列に変換するのは、ドメインデータを Smart Stack に流し込む典型パターンです。
重要ポイント
-
やること: プロジェクトを arm64 アーキテクチャに対応させ、すべての C / Objective-C 依存を確認する。
- なぜ価値があるか: watchOS 26 におけるあらゆる最適化の前提条件です。依存ライブラリで詰まると、後続の作業が一斉に止まってしまいます。
- 始め方: Xcode で Apple Watch target の Architectures を Standard Architectures に切り替え、実機で一度動かしてみてください。Float / Int の変換やポインタ演算の警告を重点的にチェックします。
-
やること: アプリでもっとも頻繁に使われるアクションを Control 化し、
kind識別子を iOS 側と共有する。- なぜ価値があるか: Control は watchOS 26 で新たに追加された「アプリを開かずに使える入口」です。Action ボタン、Smart Stack、Control Center の 3 か所で利用でき、一度実装すれば複数のシステム領域をカバーできます。
- 始め方: 「瞑想を始める」「家計簿を 1 件記録する」「よく使う画面を開く」といった単一アクションから着手し、まず
AppIntentControlConfigurationで MVP を作ったうえで、.promptsForUserConfiguration()の要否を判断します。
-
やること:
WidgetRelevanceを使い、Widget に 1〜2 個の高品質な関連性シグナルを付与する。- なぜ価値があるか: Smart Stack は Widget が適切なタイミングでユーザーの目に入るかどうかを左右します。関連性シグナルなしでは「組み込まれていない」のと同じです。
- 始め方:
RelevantContext.locationや.date(interval:kind:)から始め、アプリの中核シナリオに沿った最初のRelevanceEntriesProviderを書きます。曖昧なシグナルを一度に十数個も詰め込むのは避けましょう。
-
やること: Widget を構成可能な形に変更し、ユーザー自身に表示内容を選ばせる。
- なぜ価値があるか: 内容が固定された Widget は Smart Stack で淘汰されやすく、構成可能な Widget はユーザーが能動的に残してくれます。
- 始め方: watchOS 26 のブランチでは
recommendations()が空配列を返すようにし、旧 OS では従来どおりプリセットを返すことで、スムーズに移行できます。
-
やること: Icon Composer で watchOS 26 / iOS 26 のアイコンを書き出し直す。
- なぜ価値があるか: iPhone から Watch に転送される通知では iOS 側のアイコンが表示されるため、未更新のアイコンは新しいデザイン言語のなかで違和感のある見た目になってしまいます。
- 始め方: “Create icons with Icon Composer” セッションを参考に、iOS と watchOS のアイコンを統一して書き出し、通知と文字盤の両シナリオをカバーしてください。
関連 Session
- Meet Liquid Glass — watchOS 26 の新デザイン言語に関する公式の解説。本セッションと組み合わせて UI を更新する際は必見です。
- What’s new in widgets — Widget、Live Activity、Control の総合アップデート。クロスプラットフォームの考え方はこちらに集約されています。
- Create icons with Icon Composer — Icon Composer のワークフローと、iOS / watchOS のアイコンを更新する公式の手順。
- Go further with MapKit — watchOS 上の MapKit フルサポート、ルート計画とオーバーレイの具体的な使い方。
コメント
GitHub Issues · utterances