WWDC25:Design widgets for visionOS

visionOS 26 のアップデートのうち、まず試したのがウィジェットだった。紙やガラスといった素材感や光沢感をデジタルに落とし込むことで、実空間に存在する家具と共存するように設計されている。一貫して仮想コンテンツと一線を画するコンセプトだったのが印象的だった。近接認識なる機能によって、ユーザーとの距離に応じたコンテンツのだし分けができるとは知らなかった。


0:00 – イントロダクション

  • visionOSにおけるウィジェットは、ユーザーの現実空間に設置できる3Dオブジェクト
  • 既存のiPadアプリのウィジェットは、互換モードを有効にするだけでvisionOSに持ち込むことができ、自動的に空間的な見た目に変換される
  • ネイティブで構築することで、visionOS専用のサイズや、より空間に統合された見た目を実現できる
  • デザインの核となる4つの原則は「永続性」「固定サイズ」「カスタマイズ性」「近接認識」

3:36 – 表示の永続化

  • 一度空間に配置されたウィジェットは、セッションをまたいでも、部屋を移動しても、デバイスを再起動してもその場に固定され続ける
  • ウィジェットはホームグリッドの「ウィジェット」アプリから探し、空間に追加する
  • 机のような水平面、または壁のような垂直面に配置することで、その場に固定される
    • 水平面上に配置した時は、わずかにユーザー側に傾き、平面に影を落とす
  • ウィジェットは常にフレーム(枠)内に表示される:デジタルコンテンツと周囲環境とを繋ぐ役割
    • 新しいウィジェットを考える際は、それが部屋の一部であること(コンテクスト:キッチン、リビング、オフィス、、)を意識する
      • 例: 天気ウィジェット:実際の窓のような錯覚を生み出す
  • 同じウィジェットの複数のインスタンスを一つの空間に配置することも可能
  • ウィジェットは現実世界に存在するように振る舞う
    • 常に仮想コンテンツの背後にレンダリングされる
    • 常に物理環境の平面にスナップされる

6:39 – 固定サイズ

  • ウィジェットは現実世界の寸法に対応した、一貫性のあるサイズを持つ
  • テンプレートサイズ(小、中、大、特大)は物理的な大きさにマッピングされるため、設置される文脈(机の上、壁など)を考慮して選択することが重要
    • 生産性向上ツールでデスクの上に置くなら、小さなテンプレサイズ
    • 壁掛けのアートワークなら特大のテンプレサイズ
  • 現実のオブジェクトと空間を共有するため、印刷物や案内表示の原則を意識したデザインが必要
    • 明確な階層構造、明瞭なタイポグラフィ、慎重なスケール調整
  • ユーザーはウィジェットのサイズを75%から125%の範囲で調整できる
    • 加えて間近で見ることもできるため高解像度のアセットを使用することが推奨

8:57 – カスタマイズ性

  • スタイル:
    • Paper: 周囲の光に反応し、印刷物のように空間に溶け込むスタイル
      • Coating layer
      • Content layer: 空間に溶け込ませるための反射コーティング
    • Glass: 前景と背景に視覚的な分離を生み出し、前景の情報を常に鮮明に保つ軽量なスタイル、情報量の多いウィジェットに適している
      • Background
      • Duplicate UI layer: UIを暗めにした影により微妙な奥行きを加える
      • UI layer
      • Coating layer: 柔らかい反射仕上げ、部屋の照明に適応
  • :
    • システムが提供する豊富なカラーパレット(ライト7種、ダーク7種)をユーザーが選択し、ウィジェットを着色できる
  • マウンティングスタイル:
    • Elevated: 壁掛けの額縁のように表面に配置される
      • 水平・垂直両面に対応し、デフォルト設定
    • Recessed: 壁に埋め込まれたような見た目で、窓のような奥行き感を出す
      • 垂直面でのみ利用可能
      • 無効化が可能
  • フレーム幅:
    • 細いものから太いものまで5段階の幅をユーザーが選択できる(Recessed スタイルでは不可)
  • カスタム設定:
    • 標準のカスタマイズUIに加え、アプリ固有の設定(e.g. Musicのアルバムアートに合わせたテーマ or 時刻による自動調整)を追加できる

17:14 – 近接認識

  • ユーザーとの距離に応じて、ウィジェットが表示する情報を動的に調整する。
  • 2つの状態:
    • Default(近距離): 詳細な情報を表示 90m まで
    • Simplified(遠距離): 一目でわかるよう、必要不可欠な情報のみを表示
  • 距離に応じてボタンを追加するなど、距離に応じたインタラクション領域の変更が可能
    • インタラクションが含まれていなければ、ウィジェットタップでアプリ起動

WWDC25:Share visionOS experiences with nearby people

visionOS 関連のアップデート。visionOS 26 にアップデートしてから、ウィンドウにボタンが増えたので何かと思ったらこれのことか。今のところ身近に共有できる相手(Vision Pro ホルダー)がいないし、共有したいコンテンツも思いつかないのだが、、コンテンツのシェアリングは今のスマホやノートだと、物理的に身を寄せ合う必要があって限界があるため、今後グラス型のようにカジュアルユースなデバイスが登場するとしたら、体験共有のシームレスさが大きな売りのひとつになるかもしれない。


0:56 – 近くの人との体験共有の詳細

  • 各ウインドウのバーに新設された「共有」ボタンから、近くの人を選んで簡単に共有開始。
    • 共有されたウインドウは、全員の空間で同じ位置・サイズで表示され、ウインドウバーが緑色に変化。
    • まるで部屋にあるかのように指し示したりインタラクトすることが可能
    • 誰でもウインドウの移動・リサイズが可能で、全員の表示が同期。
    • デジタルクラウンで再センタリングも可能。手がウインドウに重なると内容がフェードし、人物が見やすくなる。
  • FaceTime との連携で、リモート参加者も空間に「ペルソナ」として登場し、近くの人と自然に混在可能。
    • ペルソナの表示位置は、共有するウィンドウのタイプ(e.g. volumetric)による
    • iOS/macOS など他プラットフォームからの参加者は、ウインドウ横にビデオ表示。
  • デフォルトでは「閲覧のみ」共有(他の人がアプリを持っていなくてもOK)。
  • インタラクティブな体験には SharePlay を採用。
    • visionOS の既存 SharePlay アプリは追加対応不要で近くの人と共有可能。
    • SharePlay の新APIで、近くの人向け体験を強化可能。

5:35 – 共有メニューからの共有の許可

  • 新しい Share メニューで GroupActivity を公開することで、ユーザーが簡単に共有を開始可能。
  • Volumetric ウインドウでは、アクティビティを公開していれば Share メニューが使える
    • 実装例の紹介
  • ImmersiveSpace ではウインドウバーがないため、アプリ内ボタンで共有開始を促す設計が必要。
  • 共有開始時に GroupSession を取得し、SharePlay を開始。
  • supportsGroupImmersiveSpacetrue に設定し、全員の空間を同期。

9:15 – 近くにいる参加者の体験の向上

  • 新APIで「近くの参加者」と「リモート参加者」を判別可能。
    • GroupSessionParticipantStateから .isNearbyWithLocalParticipant .localParticipant で判別  
    • 物理的に近い人同士を同じチームに割り当てるなど、空間に応じた体験設計が可能。

10:37 – ユーザーの相対位置へのコンテンツの配置

  • 参加者の空間内の位置(ParticipantState.pose)を取得し、各ユーザーの近くにコンテンツを配置するよう実装可能。
  • pose はリアルタイム追跡ではなく、共有開始や再センタリング時に更新。
  • seat pose(固定座席位置)も取得可能で、空間テンプレートのカスタマイズも可能。

13:20 – 共有されたメディア再生の調整

  • visionOS 26の AVPlayer/AVPlaybackCoordinator で、近くの人同士のメディア再生を完全同期するよう設計
    • 物理的に近いと、参加者のデバイスからの音ズレが顕著なため
  • GroupSession と連携し、音声・映像の遅延やエコーを防止。

15:38 – 複数のウインドウのサポート

  • 新APIで、複数 WindowGroup のうちどれをSharePlay対象にするかを明示的に指定可能。
  • .groupActivityAssociation 修飾子で、共有対象ウインドウを切り替え可能。

16:50 – アンカーされたコンテンツの共有

  • ARKitの新APIで、物理空間に固定した WorldAnchor を近くの参加者と共有可能。
    • ImmersiveSpaceは空間全体が動くため、物理的な位置固定に必要
    • WorldTrackingProvider を使用した実装方法の紹介
  • sharedWithNearbyParticipantstrue にしてアンカーを作成し、全員のデバイスで同じIDで同期。
    • worldAnchorSharingAvailability
    • これにより、家具配置アプリやコラボ体験など、物理空間を活かした共有体験が実現。
  • SharePlay 外でも独自のネットワークレイヤでも共有可能(ビジネス用アプリ)

WWDC25:Design hover interactions for visionOS

visionOS に関連するセッションビデオから。カスタムでホバーエフェクトが実装できるようになったとは、登場当初から期待していたが、いざ対応されると驚きだった。これまでは形状しかカスタマイズできなかった。ウェブアプリと同様にホバー表現が多様化するだろう、視線操作においてどんなインタラクションが有効であるかは良い題材になりそうだ。


0:33 – 基本知識

  • 重要なコンテンツは正面に配置し、インタラクティブ要素は丸みのある形状(円、ピル、角丸長方形)を推奨
  • 正確な操作のため、各要素は最低60ポイントのスペースを確保
  • 3Dオブジェクトも同様に、60ポイントは1m先で約4.4cmに相当
  • すべてのインタラクティブ要素にハイライト効果を適用し、カスタムコンポーネントや3Dオブジェクトにも同様の効果を追加

1:57 – カスタムエフェクト

  • 標準のハイライト効果に加え、独自のアニメーション(カスタムホバーエフェクト)を作成可能
    • standard appearance
    • hovered appearance
  • カスタムエフェクトは、アクション実行には使えない
    • 例: ダウンロードボタンを見つめただけではダウンロードは実行できない
  • アニメーションは3タイプ、用途により使い分け
    • 即時 instant: 見たら即時アニメーション
      • ボタンの先にさらに選択肢があることを示すインジケータの表示
      • 動画シークバーに残り時間のtooltipを表示
    • 遅延 delayed: 遅れて表示
      • ボタン下に表示されるタイトル tooltip
      • Safari profile button
    • 段階的 ramp: インスタントx遅延の段階展開
      • Environment icons: はじめ拡大だけ→しばらく後カプセル型に展開
  • ベストプラクティス:
    • アンカー要素を組み込む: e.g. タイトル
    • テキストの位置を固定
    • 隠れた要素は可視要素から表示か、見た即時に表示
    • 効果は控えめに
    • 予期しない動きを避ける
  • 実機でのテストと細かな調整が重要

9:37 – 注視してスクロール

  • 「Look to Scroll」機能で、視線だけでスクロールが可能に
  • スクロールビューの端を見つめると自動でスクロールが始まる
  • 主にリーディングやブラウジング用途のビューで有効化を推奨
  • UIコントロールが多いリストや、パララックスなど特殊なアニメーションを伴うビューには不向き
  • スクロールビューはウィンドウ全体を使い、明確な境界を設けると自然な体験になる

12:23 – 持続的なコントロール

  • 動画プレイヤーなどの自動非表示UIは、ユーザーが注視している間は表示を持続し、視線を外すと非表示に
  • 標準では手を加えずに適用されるが、カスタムコントロールの場合は、持続表示の挙動を自分で有効化する必要がある
  • メディアコントロールやセッションコントロールなど、遅延非表示UI全般で推奨

登壇メモ:集まれSwift好き!Swift愛好会スピンオフ WWDC25セッション要約会 @ DeNA

昨日、集まれSwift好き!Swift愛好会のスピンオフイベントに登壇してきた。

イベントページ:https://love-swift.connpass.com/event/355976/

これまで、会社主催のイベントでの発表はじめ、登壇経験がなかったわけではないが、社外イベントでの登壇、しかも現地発表は初めての経験だった。

ではなぜ今、登壇にチャレンジしたのかというと、単純に今年は勉強会で発表する(しかも5本!)と決めていたのにまだ一度も登壇していないところに、このイベントの登壇ハードルが非常に低く、恰好の機会だったためだ。

そんな方々のために!セッションを5分に要約して発表する会を開催します!

外部登壇と聞くと何か、誰にとっても有意義な内容を発表しなくてはいけない、、そう尻込んでしまうのだが、これはセッション内容を5分に要約するだけ。これなら誰でもできる!ということで即、登壇応募したのだった。

内容は以下。このブログでも要約メモしていた、Foundation Models framework について、Meet the Foundation Models framework を軸に、応用的なセッション内容も織り込んで内容を作り上げた。

実際、Foundation Models を使い始めたのがこのブログにも示す通り、発表の2、3日前だった。本来要約だけなので別に何か作る必要もなかったのだが、Foundation Models の概要自体は一定数の人がキャッチアップしているだろうと思い、なにかそれ以上のお土産を残したかった。が、、結局5分という時間制限の下ではしっちゃかめっちゃかになり、何かを伝えられたかすら微妙になってしまったように思う。

まあ何にしても、初めての(社外)登壇実績を解除できたということだけでも個人的には実りあったし、今年は残り4本登壇できるように頑張りたい。(来月7月は potatotips #92 iOS/Android開発Tips共有会 に登壇することが決まっている。)


最後に、今回発表に使ったデモ映像はこちら。3年前デザイナーの同僚と遊びで作ったものを、Foundation Models の活用アイデアに悩んでいたときに思い出し、掘り起こしてた。3年前のソースコードそのままで Xcode 26 ビルド通ったのが幸いし、既存実装への調整なく実現できた。すべて UIKit で実装しており、Foundation Models の出力を表示する部分だけ SwiftUI で実装し組み込んだ。

Foundation Models でオセロを作ってみたが、、

これの続き。型安全に構造化したデータを出力できる特徴を活かして何かできないか?と選んだテーマがオセロだったが、結果的にはゲームが成立しなかった。そもそもFoundation Modelsで一番最初に作るモノとしては適切でなかったかもしれない笑

紆余曲折経て、最終的に以下のようなデータモデルになった。

@Generable(description: "Represents the current state of an Othello game.")
struct OthelloGame {
    @Generable(description: "Represents the coordinates of a disc. Expressed as 'x:y' in string format (e.g., a:5).")
    struct DiscCoordinate {
        @Generable(description: "The X coordinate of the disc (a...h).")
        enum XCoordinate: String {
            case a, b, c, d, e, f, g, h
        }
        @Generable(description: "The Y coordinate of the disc (1...8).")
        enum YCoordinate: String {
            case `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`
        }
        
        @Guide(description: "The X position of the disc.")
        var x: XCoordinate
        @Guide(description: "The Y position of the disc.")
        var y: YCoordinate
    }
    
    @Guide(description: "Coordinates occupied by the white player.")
    var whiteDiscs: [DiscCoordinate] = [.init(.d, .`4`), .init(.e, .`5`)]
    
    @Guide(description: "Coordinates occupied by the black player.")
    var blackDiscs: [DiscCoordinate] = [.init(.e, .`4`), .init(.d, .`5`)]
    
    @Guide(description: "A message shown to the opponent based on the current state of the game when you make a move.")
    var message: String
}

うまくいかなかったというのは具体的には、初期状態の盤からゲームを進めるたびに最新の盤を返すよう instruction に指示していたがそれが不完全だったり、あり得ない場所に石を置いたりするといった感じだ。

ちなみにChatGPTだと次のように、間違うことはあれど一定成立するので、広義にLLMがオセロをできない、というわけではない。

たかだか2時間程度の試行錯誤なので、もっと頑張れば精度上げられたかもしれないが、大前提として以下のような向き不向きがあると思いやめた。

現状の Foundation Models 自体がオセロゲームを正確に扱えない

構造化した出力だけでなく、ChatGPT と同様に自然言語的なやりとりでも試みてみたが、初手から出力精度は ChatGPT 4o にはるかに下がる傾向があり、オンデバイスという特徴であったり、Foundation Models 自体の学習内容からして、オセロ自体に向いていないのではと考えている。

構造化させすぎることでコンテクスト上限を容易に超えてしまう

ゲームの向き不向き以外にも、数ターンでコンテクストの上限を迎える問題があった。検証してはいないのであくまで仮説だが、上述のように @Generable を構造化した分、レスポンスに要するトークンは増大すると推測している(データモデルを表す文字列が長くなるため)。もちろんゲームの特徴上、本来は会話のように過去の履歴を残す必要はなく、最後の盤とターンだけを引き継いだセッションを再生成すれば良いだろうが。


こうしたことからなんとなく掴めたことがふたつある。まずは、Foundation Models の得意分野としては、過度な構造化が不要な自然言語を軸としたユースケースで(素直に)活用するのが良いと思っている。また、構造化するしないを置いておいても、省トークンの工夫として型の命名などに気を付ける必要があるかもしれない。

次に、いきなり @Generable といったデータモデルを設計実装する前に、まず自然言語で対話してみて、ユースケースを満たす性能を有しているか、事前検証してみるのが良いと思った。Playgournd でも良いし、チャットアプリ作ってでも良い。Foundation Models が LLM をアプリに組み込みやすくしてくれているおかげで、チャットレベルであれば30分もかからず実装することができる。

WWDC25:What’s new in visionOS 26

visionOS のアップデート。SwiftUI と RealityKit との親和性が高まったことが嬉しい。ハンドトラッキングの即応性が高まったのも嬉しい。あとは、AI、Speech-to-Text、ビデオ周り、エンタープライズ向けのアップデート。

触れる機会はなさそうだが、Enterprise API でウィンドウがユーザー追従してくれそうなのが気になる。


0:00 – Introduction

  • visionOS 26のリリースにより、アプリを次のレベルに引き上げる多くの新機能が追加
  • 本セッションでは、ボリュメトリック機能、システム機能、ゲーム・アクセサリ、共有体験、没入型メディア、空間Web、エンタープライズAPIなど、幅広い新機能を紹介

1:34 – Volumetric features

  • SwiftUIに3Dレイアウトを強化する新機能が多数追加 (Spatiall layout)
    • depthAlignment でZ軸方向の整列が簡単に
    • rotation3DLayout でレイアウトを意識した回転が可能に
    • その他多くの従来のモディファイアが3Dにも対応
  • Volume内でAlert, Sheet, Menu, PopoverなどのUIプレゼンテーションが可能に
    • Volumes, Ornaments, Attachments から表示可能
  • dynamic bounds restrictions で、アプリの境界を越えてコンテンツをレンダリングし、現実世界とシームレスに融合
    • .preferredWindowClippingMargins modifier
  • 新しいObject Manipulation API や RealityKit の ManipulationComponent で、3Dオブジェクトの直感的な操作を実現
  • SwiftUI, RealityKit, ARKit間の連携が強化され
    • 座標変換やジェスチャーハンドリングが容易に ( SwiftUI view → ARKit accessor anchor でさえも可能)
    • RealityKit の Observable entity が、SwiftUI のアップデートとも連携可能に
    • ViewAttachmentComponent: UIをRealityView のコードに対してインラインに実装可能に
    • Model3D to RealityView
      • アニメーションの再生制御が可能
      • .realityViewSizingBehavior: 3D content内に対しどうサイズ調整するか

10:28 – System features

  • Apple Intelligence 機能の利用
    • Foundation Models framework により、オンデバイスLLMへのアクセスが可能に
    • Image Playground が進化し、ChatGPT 連携や新しいスタイルを追加
  • 新しいSpeech-to-text API SpeechAnalyzer と新モデル SpeechTranscriber が登場。高速・高精度な文字起こしをオンデバイスで実現。
  • ウィンドウやシーン、Quick Look コンテンツが再起動後も同じ場所に復元されるように
    • SwiftUI の復元APIにより、どのシーンに対し復元を許容するか指定可能に
      • .defaultLaunchBehavior(.supressed)
      • .restorationBehavior(.disabled)
  • WidgetKitもvisionOSに最適化され、ガラスや紙のような質感調整や、ユーザーとの距離に応じた表示切替が可能に
    • levelOfDetail widgetTexture supportedMountingStyles

15:21 – Games and spatial accessories

  • ハンドトラッキングが最大3倍高速化(90Hz)し、ゲームの応答性が向上
  • 新しい空間アクセサリ (spatial accessories) に対応
    • Sony PlayStation VR2 Sense controller: 6DoFトラッキング可能なゲームコントローラ
    • Logitech Muse: 精密な描画や彫刻に適したクリエイティブツール
    • Shared space / Full space で有効
    • RealityKit / ARKit でトラック
  • ハイエンドiPadゲームの Vision Pro 対応
    • App Store Connect 経由で、既存のハイエンドiPadゲームをvisionOSに簡単に移植可能に
    • Progressive Immersion Styleが拡張され、既存のiOS/iPadOSゲームをvisionOSに最適化しやすく
  • Compositor Services
    • ホバーエフェクト: Metal immersive apps にも対応
    • 動的なレンダー品質 (Dynamic render quality) 調整に対応
  • macOS spatial rendering: Macのレンダリング能力を使って、高品質なイマーシブコンテンツをVision Proにストリーミング可能に
  • TabletopKit が進化し、カスタムデータやカスタムアクションを簡単に追加・同期できるようになり、共有ゲームの開発が容易に

23:00 – Shared experiences

  • SharePlayと 空間ペルソナ(Spatial Personas)により、遠く離れた人とも同じ空間でコンテンツを共有する魔法のような体験が実現
  • Nearby Window Sharing により、相手の実際の位置や動きを仮想空間上に再現し、より自然な共同作業や会話を可能にする

25:03 – Immersive media ecosystem

  • RealityKit の ImagePresentatinoComponent により、3D spatial content の生成が容易に
  • Apple Immersive Video(AIV)をサードパーティアプリに直接埋め込み可能に
  • 180度、360度、WideFov フォーマットへも対応
  • Apple Projected Media Profile(APMP)

31:04 – Spatial web

  • Spatial Browsing: Safari のナビゲーションバーからボタンを押すだけで体験可能
  • visionOSのSafariで、WebXRとmodel要素によるイマーシブなWeb体験をサポート
  • Webサイト上で3Dモデルを表示したり、VR/ARコンテンツを体験したりすることが可能に
  • Web Backdrop: 開発者用の新しいプレビューツール
    • ビジターにカスタム immersive environments を提供する際に使用
  • Look to Scroll: .scrollInputBehavior(.enabled, for: .look)

34:13 – New enterprise APIs

  • メインカメラのアクセスを shared space に活かすことができ、他の spatial app と同時にカメラ利用を伴う体験が提供可能
  • Stereoscopic Main Session: 左右のメインカメラ個別/同時にアクセス可能
  • ARKit の CameraRegionProvider : スタビライズされたビデオフィードにアクセス可能
  • 新しいAPI Protected Content: .contentCaptureProtected(bool) を指定することで、特定のビューをキャプチャーから保護することができる
  • Window Follow Mode: ユーザーの位置にウィンドウが自動的に追従する
  • Nearby Window Sharing for Enterprise
    • SharedCoordinateSpaceProvider

Foundation Models framework を触ってみたが、、

以前紹介した Foundation Models framework を触ってみたが、シミューレタ起動すると例外が発生した。

let session = LanguageModelSession()
let response = try await session.respond(to: "What's a good name for a trip to Japan? Reply only with a title")
print("response: \(response)")
Passing along InferenceError::inferenceFailed::Error Domain=com.apple.UnifiedAssetFramework Code=5000 "There are no underlying assets (neither atomic instance nor asset roots) for consistency token for asset set com.apple.modelcatalog" UserInfo={NSLocalizedFailureReason=There are no underlying assets (neither atomic instance nor asset roots) for consistency token for asset set com.apple.modelcatalog} in response to ExecuteRequest

調べてみると、

Your app runs on iOS / iPadOS / visionOS / macOS 26, with Apple Intelligence enabled.

If you use a simulator, be sure that your Mac is on macOS 26, with Apple Intelligence enabled.

Apple Intelligence is available for your system language and region. If not sure, set the system language of your device to English and the region to United States.

Always check the availability when using Apple Foundation Models, as demonstrated in the Apple sample.

https://developer.apple.com/forums/thread/787445

なるほど、macOS は Sequoia 15.5 のままだったので、M2 搭載 Mac かつ Apple Intelligence 有効でも、動作要件を満たせていないのだった。(どこかのセッションで触れてた気がする)

というわけで、iPadOS 26 にアップデートした M1 搭載 iPad でビルドしたら、無事結果を得ることができた。

response: Optional(FoundationModels.LanguageModelSession.Response<Swift.String>(userPrompt: "What\'s a good name for a trip to Japan? Reply only with a title", duration: 5.951339542, content: "\"Samurai Sojourn in the Rising Sun\"", transcriptEntries: ArraySlice([(Response) "Samurai Sojourn in the Rising Sun"])))

Foundation Models のネタとして、何ができるだろうと考えていたのだが、オセロゲームの実装を閃いた。もちろんオセロ自体、ChatGPTと対戦することもできるだろうが、構造化した結果を保証する Foundation Models の強みが活かせそうだと思ったのと、ストリーム方式の結果出力に同期して状態更新を行ってみる、良いサンプルにもなりそうだからだ。

しかしChatGPT相手のオセロってどんな感じなんだろうと、ひとつ試してみたが、出力結果がブレたり、ルールガン無視したり、打てる手を否定してきたりとなかなかカオスだった笑

https://chatgpt.com/share/68594389-f13c-8005-bb90-78b4f628e1ae

これに比べて、Foundation Models framework のモデルがどれくらい精度高い/低いのか気になる。

WWDC25:What’s new in RealityKit

RealityKit のアップデートについて(AI要約+加筆)。ManipulationComponentSceneUnderstandingFlags によって仮想物体とのインタラクションや現実世界との融合がかなりラクに実装できそう。SwiftUIとの統合が進んだ点は別のセッションで網羅されてるはずなのでそちらでキャッチアップする。


0:00 – Introduction

  • RealityKitは、3Dコンテンツをアプリに統合し、リアルなレンダリングと没入感のある体験を提供するフレームワーク
  • visionOSに加え、iOS, iPadOS, macOSでもクロスプラットフォームで利用可能
  • 今年からtvOSにも対応し、AppleTV 4Kで3D体験が可能に
  • ManipulationComponent, EnvironmentBlendingComponent, MeshInstancesComponentなど、仮想と現実を融合させる新機能が多数追加

3:19 – Anchoring updates

  • RealityKitから直接ARKitのデータにアクセスできる新しい SpatialTrackingSession APIを導入
  • AnchorStateEvents を購読することで、アンカーの状態変化
    • 固定成功 DidAnchor
    • 固定解除 WillUnanchor
    • 固定失敗 DidFailToAnchor
  • ARKitAnchorComponent を通じてARKitアンカーの生のトランスフォームや範囲を取得し、仮想コンテンツを現実世界の平面などに正確に配置
  • デモアプリでは、テーブルの表面を検出し、ARKitの生のデータ (originFromAnchorTransform anchorFromExtentTransform) にアクセス

6:52 – ManipulationComponent

  • シーン内の3Dエンティティを掴んだり回転させたりするインタラクションを簡単に追加できる新しいコンポーネント
  • configureEntityを呼ぶだけで、入力や当たり判定、ホバーエフェクトなどの設定を自動追加
  • releaseBehaviorでオブジェクトを離した際の挙動(元の位置に戻るか、その場に留まるか)を制御
  • ManipulationEventsWillBegin, WillEnd など)でインタラクションの状態を検知し、物理演算のオン/オフなどを細かく制御

10:01 – Scene understanding

  • SpatialTrackingSession を通じて、ユーザーの周囲環境のメッシュ(Scene Understanding mesh)を生成
  • SceneUnderstandingFlags (.collision/.physics)
  • 生成されたメッシュを物理シミュレーションに組み込むことで、仮想オブジェクトが現実の机や床などに衝突・落下するリアルな表現が可能に

11:18 – EnvironmentBlendingComponent

  • 仮想エンティティが、静的な現実世界の物体(壁や家具など)によって自然に隠される(オクルージョン)効果を実現する新コンポーネント
  • これにより、仮想オブジェクトが現実空間にさらに溶け込んだような表現が可能になる

12:26 – MeshInstancesComponent

  • 一つのエンティティで、同じメッシュを複数回効率的に描画(インスタンシング)できる新コンポーネント
    • 従来、同じ物体を大量に配置する場合、エンティティ (ModelComponent) を大量にコピーする必要があった
  • MeshInstancesComponent を利用することで、メッシュのコピーを大量に生成するよりも、メモリと処理負荷を大幅に削減
  • LowLevelInstanceData に各インスタンスのトランスフォーム(位置・回転・拡縮)を設定するだけで、大量のオブジェクトをシーンに配置可能
    • それぞれに CustomMaterial を設定可能

16:28 – Immersive media

  • 新しい ImagePresentationComponent で、2D画像、空間写真(Spatial Photo)、空間シーン(Spatial Scene)の3種類の画像を表示可能に
  • 空間シーン(Spatial Scene: 1枚の2D写真から深度情報を持つ3D画像を生成する新技術。頭の動きに合わせて視差が生まれ、写真が立体的に見える。
  • spatial3DImage.generate() でユーザー操作をトリガーに spatial scene への変換が可能(写真アプリ)
  • ImagePresentationComponent は非同期で初期化され、表示モード(2D/空間写真など)も指定可能
  • Spatial video playback / Apple Immersive Video format について

21:43 – Accessories and more

  • Spatial Accessories: Shared space / Full space 内で、6DoF追跡、ハプティックフィードバックのサポート
  • RealityKit への SwiftUI の統合
    • ViewAttachmentComponent: entityにSwiftUI viewを直接追加
    • PresentationComponent: entityにmodal presentation, popoverを追加
    • GestureComponent: entityにSwiftUI gestureを追加
  • Entity の新API
    • attach method:entity に別の entity をアタッチ可能に:アニメーションする骨格の関節へのメッシュ追加が容易に(手動のアライン処理や構造的な transform updates が不要)
    • Entity(from: data) :RealityKit scene や UDS をオンラインソースやストリーム経由でイニシャライズ可能に
  • AVIF テクスチャのサポート
  • Hover Effect GroupID
    • ホバーエフェクト間の関連付けが可能
    • 同一のGroupIDで、構造に関係なくホバーの切り替えが共有される
  • Post processing for RealityView

WWDC25:Explore new advances in App Intents

Get to know App Intent 」つながりで。AI要約してもらったが、要約されすぎて動画の内容が網羅されてなかったのと、そもそも App Intent 自体に全然馴染みなかったので理解追いつかず、追加で詳解してもらった(Result/Confirmation snippets の更新手順まわり)。なので正しいかわからないが個人的には腑に落ちた。


0:00 – Introduction

  • App Intentsは、アプリの機能をショートカット、Spotlight、Visual Intelligenceなどに統合するためのフレームワーク
  • 本セッションでは、インタラクティブスニペット、新しいシステム統合、ユーザー体験の改善、便利なAPIなど、App Intentsの最新の進化について解説

0:55 – Interactive snippets

  • App Intentの結果や確認画面を、インタラクティブなUI(スニペット)として表示できる新機能
    • 冒頭のスライドでは、Control Center 上のボタンからアクションし、その場で Interactive snippets を表示している
  • Snippet Intentプロトコルに準拠し、パラメータとアプリの状態に基づいてビューをレンダリング
    • スニペット内のボタンやトグルに既存のApp Intentを関連付け、ユーザー操作に応じてアプリの状態を更新し、スニペットを再描画できる
  • Result Snippet の更新手順
    • 最初の app intent が実行され、その結果として、どの情報を表示するかのテンプレート(Parameterized Result Snippet Intent)を返す
    • 次にシステムが、先ほどのテンプレートに具体的なデータ(パラメータ)を埋め込む。例えば「最も近いランドマーク」の情報を、クエリを通じて取得、設定する
    • データが設定されたインテントが perform メソッドを実行し、最終的にユーザーが見るUI(SwiftUI view)を描画する
    • 描画されたビュー内のボタンやトグルには、他の app intent が関連付けられている。ユーザーがこれらをタップすると、新しいアクションが実行され、スニペットが更新される、というサイクルが生じる
  • Confirmation Snippet の更新手順
    • Result Snippet上のボタンをユーザーがタップすると、関連付けられた intent が実行される
    • ↑の intent は、最終的なアクションをすぐに実行するのではなく、requestConfirmation を呼び出して、確認用の新しいスニペット(Parameterized Confirmation Snippet Intent)を返す
    • この Confirmation Snippet の表示以降は Result Snippet と同じ手順
    • ユーザーが最終的な確認ボタン(「検索開始」など)をタップすると、requestConfirmation が完了し、リクエスト元の inten 処理が再開される(チケット検索などの本来の処理)
  • システムは、snippet が表示されている限りアプリを終了しないため、メモリやデータベースに状態を保持しようとする必要はない

8:15 – New system integrations

  • Image Search: カメラやスクリーンショットからの画像検索結果に、アプリのコンテンツを表示可能に。IntentValueQuery に準拠し、SemanticContentDescriptor を入力としてエンティティを返すクエリを実装。
    • さらに検索結果を見たい場合にアプリに遷移する導線の実装:semanticContentSearch schema
    • @UnionValues
      • 従来、1つのクエリは1つの型のエンティティしか返せなかった
      • 「この写真に関連するランドマークと、そのランドマークが含まれるコレクションの両方を同時に表示したい」というニーズが実現できなかった
      • UnionValues により、1つのクエリで複数の型を返せる
  • Onscreen Entities: NSUserActivity を使い、画面上のコンテンツにエンティティを関連付けることで、SiriやChatGPT  (にスクリーンショットを送ることで) がそのコンテンツについて応答できるようになる。Transferable でPDFなどのデータ形式も提供可能。
  • Spotlight: MacのSpotlightから直接アクションを実行可能に。IndexedEntityPredictableIntent を活用し、検索候補の精度や関連性を向上。

15:01 – User experience refinements

  • UndoableIntent: App Intentで実行したアクションを、標準の「取り消し」ジェスチャーで元に戻せるようになるプロトコル。
  • Multiple-choice API: 複数の選択肢を提示し、ユーザーに選ばせるUIを簡単に実装可能。requestChoiceメソッドで選択肢を提示し、結果に応じて処理を分岐。
  • Supported Modes: background foreground(immediate/dynamic/deferred)などのモードをサポートし、Siriからの実行時やアプリ内での実行時で、Intentの振る舞い(UI表示の有無など)を動的に制御。

21:02 – Convenience APIs

  • View Control APIs: UIナビゲーションのロジックを Intent から分離し、SwiftUI ビュー側で onAppIntentExecution モディファイアを使ってハンドリング。コードの関心を分離し、見通しを良くする。
  • ComputedProperty: App Entity のプロパティを、値をコピーするのではなく、元のデータソースから直接算出できるマクロ。
  • DeferredProperty: App Entity のプロパティの値を、必要になるまで(例:ショートカットアプリで表示されるまで)非同期で遅延取得できるマクロ。高コストな処理を効率化。

WWDC25:Design interactive snippets

インタラクティブスニペットのデザインについて。前回「Get to know App Intents」で学んだ App Intents の活かし方のひとつとして見てみた。


0.00 – Introduction

  • Interactive snippets は、App Intents によって駆動するコンタクトなビュー
  • アップデート情報やクイックアクションを表示し、App Intents をサポートするどこでも表示可能 (Spotlight, Siri, Shortcuts app)
  • ボタンといった要素もサポートした

1.30 – Appearance

  • Larget type: スニペットの見やすさに寄与するのが文字サイズ、システムのデフォルトサイズよりも大きい
    • 大きな文字サイズが重要な情報への注意を引く
  • レイアウトが乱雑にならないよう、文字の周囲に十分な余白を確保すること
  • Consistent margins: 周囲に一定マージンを維持すること
    • スニペットがオーガナイズされ、ユーザーが何が起こっているかに集中できる
    • ContainerRelativeShapeAPI
  • Concise content: 340 points を超えるコンテントを含めないこと
    • 最も重要な情報に絞り、簡潔に示すこと
    • 詳細を知りたければ、スニペットから特定のビューにリンクすることができる
  • Clear contrast: コンテントの上に他のコンテンツを表示する際、アプリの visual identity をベースにし背景を vibrant するのが有効
    • 読みやすさを損なうことがあるので、背景とコンテンツとのコントラスト比を上げると良い

3.25 – Interaction

  • データ更新時、文字に対してスケールとブラーを伴うことで、明確なビジュアルフィードバックを与えられる
    • スニペット内で情報更新し、アクションが成功したことを示すことで、App Intent がユーザーのルーチン内に信頼を構築できる
  • ボタンを複数含められる
    • メインタスクを補う、明確で関連性のあるアクションであるべき
  • インタラクティブでなくとも、最新情報にアニメーションを伴って更新できる

4.49 – Types

  • ふたつのスニペットタイプ
    • Result (結果)
      • 確認 (confirmation) の結果、またはそれ以上のアクションを必要としない情報を表示
      • フォローアップの必要がないのでボタンラベルは “Done (完了)” とする
      • 注文状況の確認などに有効
    • Confirmation (確認)
      • 結果 (result) を表示する前にアクションを要する場合に使用
      • コーヒー注文の例: 数量変更、注文ボタンをタップするまでは注文がされない
      • ボタンラベルは明確な動詞とする (e.g. “Order (注文)”)
        • 事前定義から選ぶことが可能
      • アクション後は、結果 (result) を表示し、インテントの挙動をユーザーが理解する
  • ダイアログ
    • Siri が App Intent の代弁をするときに表示
    • AirPods 使用時など、ボイスファーストなインタラクションに必須
      • 画面を見ていないくても耳で(result / confirmation を)聞くことができる
    • ダイアログが表示されなくてもスニペットの内容を理解できるように設計するべき