WWDC Quick Look 💓 By SwiftGGTeam
What's new in watchOS 8

What's new in watchOS 8

元の動画を見る

ハイライト

watchOS 8 では Always-On Display が文字盤からサードパーティ App まで拡張されました。isLuminanceReduced 環境値と TimelineView と組み合わせることで、手首を下げた状態でも表示を保ちながら、更新頻度を制御しプライバシーを守れます。

主要内容

Apple Watch App を開発したとします。ユーザーが手首を上げれば、すべて正常に動きます。しかし手首を下げると、画面が真っ暗になるか、ぼやけた UI が表示される——これが watchOS 7 の挙動でした。

watchOS 8 がこれを変えます。

watchOS 8 から、サードパーティ App も Always-On 状態で表示を維持できます。Apple Watch Series 5 以降が対応しています。手首を上げなくても、ちらっと App の内容を確認できます。

ここで 2 つの問題がすぐに浮かびます。

1 つ目、低輝度で UI をどう設計するか。

2 つ目、手首を下げたときにコンテンツをどう更新するか。

Apple は API の一式で両方に答えています。

詳細

isLuminanceReduced: Always-On 状態の検知

02:40

watchOS 8 では新しい SwiftUI 環境プロパティが導入されました。

@Environment(\.isLuminanceReduced) var isLuminanceReduced

時計が Always-On 状態に入ると、システムは画面輝度を自動的に下げます。isLuminanceReducedtrue になり、App はそれに応じて UI を調整できます。

Xcode Preview でもこの状態をシミュレートできます。

ContentView().environment(\.isLuminanceReduced, true)

03:00

キーポイント:

  • @Environment はシステム環境から状態を読み取る
  • 手首を下げて低輝度のとき isLuminanceReducedtrue
  • Preview とシミュレーターでシミュレート可能。シミュレーターウィンドウに wrist-down 用のボタンがある

セッションでは 3 つの実 App のデザイン例が示されました。

Fitbod は界面構造の一貫性を保ち、副次テキストだけをさらに暗くします。

AnyList はリスト項目の背景色を外し、「ギリシャヨーグルトの味」「牛乳の数量」などの副次情報を暗くし、主タイトルを際立たせます。

Pandora はアルバムアートを外して暗いアウトラインに替え、下部コントロールバーも暗くし、曲名とアーティスト名だけをはっきり表示します。

03:50

機密情報も扱う必要があります。銀行残高や個人の健康データは、手首を下げたときにぼかすか非表示にすべきです。SwiftUI の .redacted(reason:) modifier は widget と同じモデルを共有します。

アニメーションは最初のフレームか静止状態にリセットし、途中で止めないでください。

TimelineView: 手首を下げたときの更新リズム

06:59

アクティブなセッションがある App(workout やオーディオ再生など)は、手首を下げたとき UI を最大 1 秒に 1 回まで更新できます。アクティブセッションがない App は最大 1 分に 1 回です。

SwiftUI の TimelineView がこの定時更新を担当します。schedule を受け取り、時間に沿って View を構築します。

watchOS 8 には 5 種類の組み込み schedule があります。

  • EveryMinute: 毎分更新。システム時計に合わせ、ちょうど分のタイミングで発火
  • Periodic: カスタム間隔(例: 2 分ごと)。システム時計には合わせない
  • Explicit: 指定した時刻に更新。精密なタイミング向け
  • Custom: 混合戦略(例: 59 分は毎分、最後 60 秒は毎秒)
  • Animation: アニメーション専用

07:18

典型的な TimelineView の使い方:

TimelineView(.everyMinute) { context in
    Text(context.date, style: .time)
}

キーポイント:

  • TimelineView のクロージャは現在日時を含む TimelineViewContext を受け取る
  • 非アクティブセッションで 1 分より速い更新を要求しても試行はされるが保証されない
  • デフォルトでは 2 分後に文字盤に戻るが、ユーザーは設定で変更可能。App は長時間表示に備えるべき

HealthKit バックグラウンド配信

08:58

watchOS 8 では iOS にあった HealthKit バックグラウンド配信が Watch App にも来ました。設定は iOS と同じです。

let query = HKObserverQuery(
    sampleType: heartRateType,
    predicate: nil
) { query, completionHandler, error in
    fetchLatestHeartRateData()
    completionHandler()
}

healthStore.execute(query)
healthStore.enableBackgroundDelivery(
    for: heartRateType,
    frequency: .immediate
) { success, error in
    // バックグラウンド配信を有効化
}

09:13

キーポイント:

  • HKObserverQuery はデータ変化を監視する
  • enableBackgroundDelivery でバックグラウンド起動を有効化
  • 通常の App は最大 1 時間に 1 回まで起動
  • アクティブな文字盤に complications があれば最大 1 時間に 4 回
  • すべての起動回数はバックグラウンド更新予算にカウントされ、上限は 1 時間 4 回
  • 転倒、低酸素、心拍異常など重要なデータ型は即時配信
  • その他のデータ型は 1 時間以上の間隔で配信

HealthKit 認可フォームも更新され、App が Apple Watch でより頻繁に健康データにアクセスすることをユーザーに伝えます。

Bluetooth デバイスのバックグラウンド接続

10:49

watchOS 4 から Bluetooth デバイスの Apple Watch 直結が可能でした。watchOS 8 の新機能は、バックグラウンド更新中の接続です。

complications が Bluetooth アクセサリから継続的にデータを取得できます。例: Qardio の医療用 ECG、Sonra Watch のサッカー選手向け GPS トラッカー。

バックグラウンド更新は 1 時間最大 4 回の接続機会を提供し、これもバックグラウンド更新予算にカウントされます。

Apple は WKRefreshBackgroundTask に expiration handler を追加しました。

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
    for task in backgroundTasks {
        task.expirationHandler = {
            // 時間切れ前に接続をクリーンアップ
        }
        // Bluetooth デバイスに接続してデータ取得
    }
}

12:35

キーポイント:

  • Bluetooth の初回接続は App がフォアグラウンドである必要がある。バックグラウンドでは新規接続不可
  • 接続確立後は、バックグラウンド更新中に再接続してデータ取得可能
  • データ処理は短時間で完了する必要がある
  • expirationHandler で時間切れ前にきれいに終了できる

位置情報ベースのリージョン通知

13:15

watchOS 8 は UNLocationNotificationTrigger をサポートし、指定リージョンへの入退場時に通知できます。

let center = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
let region = CLCircularRegion(
    center: center,
    radius: 200,
    identifier: "gym"
)
region.notifyOnEntry = true

let trigger = UNLocationNotificationTrigger(region: region, repeats: false)
let content = UNMutableNotificationContent()
content.title = "ジムに到着"
content.body = "トレーニングの記録を始めましょう"

let request = UNNotificationRequest(
    identifier: "gym-entry",
    content: content,
    trigger: trigger
)
UNUserNotificationCenter.current().add(request)

13:40

キーポイント:

  • CLCircularRegion で円形ジオフェンスを定義
  • UNLocationNotificationTrigger はリージョンに基づいて通知を発火
  • 「使用中」の位置情報許可が必要
  • 最初は静的な通知。タップ後に動的コンテンツを表示しプライバシーを保護
  • リージョン半径は数百メートル程度を推奨。ユーザーが明確に関心を持つ場所だけ設定

Core Location の location button も watchOS に登場。ボタンタップで一度限りの位置許可が得られ、毎回ダイアログは出ません。

その他のシステム強化

15:18

watchOS 8 には注目すべき改善もあります。

  • 睡眠時の呼吸数: Apple Watch が睡眠中の呼吸数を測定。App は HealthKit 経由で読み取り可能
  • AssistiveTouch: ジェスチャー認識で上肢に差のあるユーザーが操作しやすく
  • 大きなアクセシビリティ文字: より大きなアクセシビリティ文字サイズ
  • 大タイトル: スクロール View 上部で iOS 風の大タイトルをサポート
  • テキスト入力の改善: App ごとの Scribble/音声入力の好みを記憶し、素早く切り替え
  • 検索 API: searchable modifier でカスタム検索候補をサポート
  • リストのスワイプ操作: リスト項目にカスタムスワイプ操作(お気に入りなど)
  • Button roles: ボタン種別(destructive など)の区別、prominence と追加の触覚フィードバック
  • Canvas API: SwiftUI Canvas が watchOS に。GPU によるプログラム描画をサポート

重要ポイント

  1. 手首を下げても見えるタイマー App を作る。 TimelineView + EveryMinute schedule で、料理や運動中に手首を下げても残り時間を表示。最後 60 秒は毎秒更新に切り替え。入口 API: TimelineView + Custom schedule。

  2. Bluetooth 血糖計の complication 連携を作る。 バックグラウンド更新中に血糖計に接続し、1 時間に 1 回 complication を更新。expirationHandler で接続を確実に閉じる。入口 API: CBCentralManager + WKRefreshBackgroundTask

  3. 位置情報ベースのフィットネスリマインダー App を作る。 ジム到着でトレーニング記録開始、退出で保存を促す。UNLocationNotificationTrigger で 200 m のジオフェンス。入口 API: CLCircularRegion + UNLocationNotificationTrigger

  4. 睡眠呼吸モニタリング dashboard を作る。 watchOS 8 の睡眠呼吸数データで、毎朝の推移を表示。HealthKit バックグラウンド配信と組み合わせ、手動更新不要。入口 API: HKQuantityType.respiratoryRate)+ HKObserverQuery

  5. Always-On 向けの音楽再生 UI を作る。 手首を下げたらアルバムアートと再生コントロールを隠し、曲名とアーティスト名だけ表示。isLuminanceReduced で状態ごとの UI 階層を制御。入口 API: @Environment(\.isLuminanceReduced) + .redacted(reason:)

関連セッション

コメント

GitHub Issues · utterances