View in English

  • Apple Developer
    • 今すぐ始める

    「今すぐ始める」を詳しく見る

    • 概要
    • 学ぶ
    • Apple Developer Program

    最新情報

    • 最新ニュース
    • Hello Developer
    • プラットフォーム

    プラットフォームを詳しく見る

    • Appleプラットフォーム
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    特集

    • デザイン
    • 配信
    • ゲーム
    • アクセサリ
    • Web
    • Home
    • CarPlay
    • テクノロジー

    テクノロジーを詳しく見る

    • 概要
    • Xcode
    • Swift
    • SwiftUI

    特集

    • アクセシビリティ
    • App Intent
    • Apple Intelligence
    • ゲーム
    • 機械学習とAI
    • セキュリティ
    • Xcode Cloud
    • コミュニティ

    コミュニティを詳しく見る

    • 概要
    • 「Appleに相談」イベント
    • コミュニティによるイベント
    • デベロッパフォーラム
    • オープンソース

    特集

    • WWDC
    • Swift Student Challenge
    • デベロッパストーリー
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Center
    • ドキュメント

    ドキュメントを詳しく見る

    • ドキュメントライブラリ
    • テクノロジー概要
    • サンプルコード
    • ヒューマンインターフェイスガイドライン
    • ビデオ

    リリースノート

    • 注目のアップデート
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • ダウンロード

    ダウンロードを詳しく見る

    • すべてのダウンロード
    • オペレーティングシステム
    • アプリ
    • デザインリソース

    特集

    • Xcode
    • TestFlight
    • フォント
    • SF Symbols
    • Icon Composer
    • サポート

    サポートを詳しく見る

    • 概要
    • ヘルプガイド
    • デベロッパフォーラム
    • フィードバックアシスタント
    • お問い合わせ

    特集

    • アカウントヘルプ
    • App Reviewガイドライン
    • App Store Connectヘルプ
    • 近日導入予定の要件
    • 契約およびガイドライン
    • システムステータス
  • クイックリンク

    • イベント
    • ニュース
    • Forum
    • サンプルコード
    • ビデオ
 

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • すべてのビデオ
  • 利用方法

その他のビデオ

  • 概要
  • Summary
  • トランスクリプト
  • コード
  • アプリにビジュアルインテリジェンスを統合するためのベストプラクティス

    ビジュアルインテリジェンスによって、アプリ内のコンテンツの発見をどのように変革できるかについて解説します。エンティティの定義や画像の処理を行う方法、複数の結果タイプの効果的な扱い方を確認しましょう。スピードと関連性を最適化するためのベストプラクティスや、ワンタップでコンテンツを開いたり再生したりするなどのダイレクトアクションを実現するためのIntentの使用方法を紹介します。

    関連する章

    • 0:07 - Introduction
    • 2:02 - Defining your content
    • 5:03 - Implementing a query
    • 8:18 - Opening results
    • 10:03 - Mac and iPad adoption
    • 12:27 - Returning multiple result types
    • 12:56 - Continuing search in your app
    • 14:27 - System store integrations
    • 17:16 - Next steps

    リソース

    • Integrating your app with visual intelligence
    • Visual Intelligence
      • HDビデオ
      • SDビデオ
  • このビデオを検索

    こんにちは、Davidです。

    System ExperienceのMLエンジニアです。

    Visual Intelligenceを使って 何かを作ってみましょう。 このセッションでは、 アプリをVisual Intelligenceと 統合する手順を ステップごとに説明し、 ベストプラクティスもご紹介します。 Visual Intelligenceが導入されて以来、 多くの人がそれを活用して 周囲の情報を 素早く把握しています。 実際の周囲の環境であれ、 iPhoneの画面であれ。

    今年は、連絡先への追加などの 新機能を追加しました。 複数のカレンダーイベントの保存や 医療機器のログ記録も可能になります。

    さらに、Visual Intelligenceを iPadとmacOSにも展開します。

    では、アプリをこの体験に 組み込むにはどうすればいいでしょうか? 実際に作りながら説明します。

    私は音楽を聴いたり、 新しい音楽を発見するのが大好きです。 そこで、アルバムを発見したり 近日開催のコンサートを 見つけられるアプリを作りたいと思います。

    今日作るものをご紹介します。 これが私の音楽アプリです。 アルバムを閲覧したり、 近日開催のコンサートを確認したり、 タップするだけで 何でも聴き始めることができます。 アルバムアートワークの写真や スクリーンショットを撮って、 ハイライトして検索すると、 マッチしたアルバムとコンサートが Visual Intelligenceに表示されます。 近日開催のコンサートについての 投稿をキャプチャして、

    Visual Intelligenceを使って イベントをカレンダーに追加することもできます。

    するとコンサートが アプリに自動的に表示されます。 このセッションが終わる頃には、 これらすべての作り方がわかるようになります。 Visual Intelligenceとの統合を 最大限に活用するには、 いくつかのステップがあります。 今日はそれをご紹介します。 まず、App entitiesを使って アプリから返すコンテンツを定義します。 App entitiesを使います。

    次に、Visual Intelligenceが 見つけられるよう アプリのコンテンツを返す クエリを実装します。

    それから、iOS以外にも統合を拡張して MacとiPadに対応させます。 各プラットフォームの 考慮事項も説明します。

    最後に、システムストアとの統合を探ります。 Visual Intelligenceが 抽出した情報を アプリが自動的に読み取れる 一般的なデータストアを すでに採用しているかもしれません。 Image Searchの基本から 始めましょう。 Image Searchの統合は App Intentsと Visual Intelligenceフレームワークの 両方を活用します。 App Intentsが初めての方は、 WWDC25のこれらのセッションを ご覧になることをお勧めします。

    Image Searchの統合の最初のステップは、 返すコンテンツを定義することです。

    そのために、App Intentsフレームワークの App entitiesを使います。 App entitiesはアプリ内の名詞です。 このアプリでは、Image Searchで まず視覚的に類似したアルバムを返したいので、 アルバムエンティティを定義します。

    コードで確認してみましょう。

    まず、AlbumEntityを定義します。 Visual Intelligenceが検索結果に 表示できるようにします。

    まず、デフォルトのEntityQueryを追加します。 そして、App entityで標準的な typeDisplayRepresentationを追加します。

    次に、エンティティのコンテンツを定義します。

    各AlbumEntityには識別子があります。 name、artistName、そしてアルバムアートワーク用の サムネイルデータが含まれます。

    そして、displayRepresentationを追加します。 これによって、Visual Intelligenceに 各結果の表示方法を伝えます。

    今定義した表示表現について お話しましょう。

    これはImage Searchの結果で 最初に見えるものです。 スペースはあまりありません。 タイトルとサブタイトルに 約3行のテキストが使えます。 そしてサムネイル画像も表示されます。

    最も重要な識別情報を ここに置くことが ベストプラクティスです。 私の場合、アルバム名とアーティストです。

    画像URLを使って displayRepresentationを初期化する場合は、 画像URLを使う場合は、 適切な場合はサムネイルサイズの画像を 提供することをお勧めします。 フル解像度のアセットへのリンクよりも 効果的です。

    例えば、常に複数の結果を 返す場合は、 小さい画像を使うと 結果の読み込みが速くなります。 そして2列レイアウトでも 見栄えがよくなります。

    ただし、1つの結果しか返さない場合は、 この画像が結果シートの 全幅を占めることを覚えておいてください。

    エンティティの定義ができたので、 Visual Intelligenceは実際に どうやってアプリに結果を問い合わせるのでしょうか? それが Intent value queryの役割です。 Intent value queryは 軽量なクエリプロトコルで、 システムにエンティティの値を提供します。

    すでにお持ちかもしれません。 Siriでアプリを動かすために App Intentsを採用していれば。

    Visual Intelligenceでは、 主な違いは入力にあります。 システムがSemanticContentDescriptorを渡します。 キャプチャされた画像に関する 情報が含まれています。 コードに戻って実装しましょう。

    IntentValueQueryプロトコルを採用します。 そして、SemanticContentDescriptorを入力として values for requirementを実装します。

    本文では、入力から pixelBufferを取り出して、 catalog.searchメソッドに渡します。 これがマッチしたアルバムを返します。

    でも、その検索は実際にどのように機能するのでしょうか? 次に見てみましょう。

    このアプリでは、保存済みアルバムの ローカルカタログを使ってデバイス上で検索します。

    Visionフレームワークを使います。 コンピュータビジョンタスク向けの 事前訓練された機械学習モデルを提供しています。

    カタログの各エントリには featurePrintが含まれます。 画像のコンパクトな数値表現で、 画像の類似性を 比較するために使います。

    feature printを計算する関数を定義します。 GenerateImageFeaturePrintRequestを使います。

    カタログ内のアルバムに対して これを事前計算しておきます。 クエリ時にこの計算を 行う必要がないようにします。

    クエリでは、まずpixelBufferを CGImageに変換します。 VideoToolboxを使います。 次に、この画像の新しい feature printを生成します。

    それをカタログの事前計算された feature printと比較します。 最大距離しきい値を適用して 類似していない結果をフィルタリングします。

    最後に、類似度でソートして 上位の結果を返します。

    いくつか注目すべき点があります。 アルバムカタログの feature printを事前計算して、 クエリを高速に保ちます。

    結果を類似度でソートして、 最もマッチするものが先頭に来るようにします。 デバイス上で検索する場合でも サーバーにアクセスする場合でも、 同じ原則が適用されます。 結果を素早くランク付けして返しましょう。

    また、返す結果の数を 制限することもお勧めします。 関連性を確保するためです。

    良いマッチが見つからない場合は、 空の配列を返せます。 システムが空のレスポンスの 表示を処理します。

    Visionフレームワークの APIも 確認することをお勧めします。 アプリで使える画像処理技術について 詳しく学べます。 feature printで表面をなぞっただけですが、 テキストの抽出など さらに多くのことができます。 バーコードのスキャン、顔の検出、 画像の分類など、いくつか例を挙げました。 これらは非常に有用な技術です。 アプリのビジュアル検索の 機能を拡張するために役立ちます。

    では、結果をタップしたときに アプリの適切な画面に 誘導するにはどうすればいいでしょうか? そのために、OpenIntentが必要です。 Image Searchの結果でアルバムをタップすると、 システムが選択されたエンティティで このintentを呼び出します。

    私のperformメソッドは アルバム詳細ページに移動します。

    OpenIntentは選択したコンテンツに 直接誘導する必要があります。

    エンティティ用のOpenIntentが すでにある場合は、 他の機能を動かすために App Intentsを採用したものでも、 ここでも再利用できます。 Visual Intelligence専用に 別のものを用意する必要はありません。

    軽量に保つことをお勧めします。 このメソッドはアプリが フォアグラウンドに来るときに実行されます。 ナビゲーションを行い、 重い処理は ビューが表示されてから行いましょう。

    これで基本的なImage Searchの 統合に必要なものはすべてです。 ここまで作ったものを 見てみましょう。

    友人がこのおすすめを送ってきました。 Visual Intelligenceを使って アプリで聴き始めてみましょう。 スクリーンショットを撮って、 ハイライトして検索します。 利用可能なプロバイダーから アプリを選択します。

    クエリが機能しました。 アルバムを見つけて 上位の結果として返すことができました。

    アプリは他の採用アプリと並んで ここに表示されることも注目に値します。

    システムが順序を決定するのは デバイスで利用可能な Image Searchプロバイダーに基づいています。 この結果をタップすると、 アプリのアルバムページに直接移動します。

    これがエンティティ、クエリ、 そしてOpenIntentが連携して動作している様子です。 では、さらに多くのプラットフォームに 対応させましょう。 今年は、 Visual IntelligenceがiPadOSと macOSでも利用可能になります。 同じAPIがこれらの新しいプラットフォームでも 利用可能です。 アプリへの変更は最小限で済みます。

    IntentValueQuery、エンティティ、 そしてOpenIntentはすべて iOS、iPadOS、macOSで動作します。 これは先ほど書いたコードと同じです。

    ただし、 覚えておくべきプラットフォームの 違いがいくつかあります。

    iOSでは、人々はカメラを通じて Visual Intelligenceを使うことが多く、 レコードやコンサートポスターなどの 物理的なオブジェクトをキャプチャします。

    macOSとiPadでは、メインのエントリーポイントは スクリーンショット、つまりデジタルメディアのキャプチャです。

    検索が両方の種類のコンテンツを うまく処理できるようにしましょう。

    Macでは、 入力のpixel bufferが iPhoneよりもはるかに大きくなる場合があることを 覚えておいてください。

    ユースケースに応じて リサイズが必要かどうかを検討してください。

    macOS向けにアプリをビルドして どう見えるか確認しましょう。

    同じ画像の スクリーンショットを撮ります。 クエリやエンティティのコードを 変更せずに、 アプリのImage Searchが macOSで動作します。

    結果は素晴らしいです。

    基本をカバーしたので、 アプリにさらに多くの 機能を追加したいと思います。

    視覚的に類似したアルバムだけでなく、 そのアルバムのアーティストの 近日開催のコンサートも検索できたらどうでしょう? そのために、UnionValueを使えます。

    アプリはSemanticContentDescriptorを 受け付ける IntentValueQueryを1つしか持てないので、 各エンティティタイプ(アルバムとコンサート)に ケースを持つ@UnionValue enumを定義します。

    エンティティタイプが2つになったので、 それぞれにOpenIntentが必要です。

    次に、このunionタイプを返すように クエリを更新します。

    まず上位のマッチするアルバムを検索し、 そのアルバムのアーティストを使って 近くのコンサートを見つけ、 それらを1つの結果リストに まとめます。

    アプリで複数のタイプの結果を返すことが 理にかなっているか検討してください。

    単にピクセルのマッチングを超えた、 アプリが返せる さまざまなコンテンツタイプについて 考える価値があります。 画像の類似性でアルバムを見つけて、 そのアーティスト名を使って 近くのコンサートを表示しました。 全く異なる種類の結果です。

    文脈に基づいて返すコンテンツの タイプについて 自由に創造性を発揮してください。

    最後のタッチとして、すぐに求める結果が 見つからない場合のために、 アプリ内で検索を続けられる 簡単な方法を提供したいと思います。

    そのために semanticContentSearchスキーマを使えます。 semanticContentSearchスキーマに準拠した intentを作成します。

    システムがsemanticContentプロパティを 自動的に提供します。 これはpixel bufferを持つ、 以前見たSemanticContentDescriptorと同じです。

    performでは、 アプリ内の検索ビューに移動します。 事前に入力された検索結果と共に。

    「もっと見る」をタップすると、 アプリのフルな検索体験に 移動します。 semantic content searchを使って フルな検索体験に 続けられる方法を提供することが ベストプラクティスです。

    入力コンテキストに基づいて 検索ビューを事前に入力できます。 ゼロから始めるよりも効果的です。

    アプリはVisual Intelligenceの結果ビューよりも はるかに多くを表示できます。 フィルター、カテゴリー、 コンテンツの深さすべて。 それを活用してください。

    ここまで作ったものすべてを 実際に見てみましょう。

    同じアルバムの スクリーンショットをもう一枚撮ります。 アプリがマッチするアルバムとコンサートを Visual Intelligenceに返します。

    もっと閲覧したい場合は、 「もっと見る」ボタンをタップすると アプリのフルな検索に移動します。

    アプリがVisual Intelligenceに 結果を提供することについてお話しました。 しかし、もう一つの面もあります。

    アプリはVisual Intelligenceから データを受け取ることもできます。 システムストアの統合を通じて。 Visual Intelligenceへの結果提供は Image Searchの統合を通じて行われます。 これはここまで作ったものすべてです。

    他のVisual Intelligenceのアクションは システムストアにデータを書き込みます。 これにより開発者は 共有システムデータへのブリッジを得られます。

    イベントはEventKitで読み取り、 連絡先情報はContacts、 医療機器の測定値は HealthKitで読み取れます。 アプリがすでにこれらのフレームワークの データストアから読み取っているなら、 Visual Intelligenceが 自動的に新しい入力源になります。

    このアプリでは、人々が興味を持っている 近日開催のコンサートを把握して、 事前に聴く曲を提案できるようにしたいです。 EventKitの統合を追加して これらのイベントにアクセスしましょう。

    これが私のUpcomingConcertManagerです。 EKEventStoreを使用しています。

    カレンダーへの読み取りアクセスをリクエストして、 近日開催のイベントをクエリします。

    このアプリでは、近い将来の イベントをフィルタリングします。 カタログのアーティストにマッチするものです。

    通知オブザーバーも追加します。 Visual Intelligenceによって作成されたものも含む 新しいイベントが 自動的に表示されるようにします。

    では最後のピースを見てみましょう。

    近日開催のコンサートについての ソーシャルメディアの投稿をキャプチャすると、 Visual Intelligenceがイベントを検出して カレンダーに追加できます。

    アプリを開くと、 「近日開催のコンサート」に すでに表示されており、聴き始める提案もあります。

    同じパターンが 他のシステムストアにも適用されます。

    Visual Intelligenceを通じて追加された連絡先は、 たとえば名刺から、 CNContactStoreを通じてアクセスできます。

    Visual Intelligenceによってキャプチャされた 医療機器の測定値は、 血圧計のディスプレイ、 血糖値計や体重計から HKHealthStoreを使ってクエリできます。 HealthKitから読み取る ヘルスまたはフィットネスアプリであれば、 Visual Intelligenceが データを記録するための別の方法になります。 手動入力なしで。 今日は多くのことをカバーしました。 まとめると、Visual Intelligenceはアプリに 2つの強力な統合ポイントを提供します。

    Visual Intelligenceに結果を提供できます。 Image Searchを通じて。 そして、Visual Intelligenceから データを受け取ることができます。 システムストアの統合を通じて。 Visual IntelligenceがiOS、iPadOS、macOSで 利用可能になった今、 統合はデバイス全体で ユーザーにリーチできます。

    詳しく知りたい場合は、 デベロッパーウェブサイトで 利用可能なドキュメントをご確認ください。

    関連セッションも視聴して さらなる機能を探ることができます。 App IntentsとVisionフレームワークについて。

    ご視聴ありがとうございました。

    • 3:21 - Define the content you want to return as an App Entity

      // Define the content you want to return as an App Entity
        import AppIntents
        
        struct AlbumEntity: AppEntity {
            var id: String
            @Property var name: String
            @Property var artistName: String
            var coverArtData: Data
            
            var displayRepresentation: DisplayRepresentation {
                DisplayRepresentation( 
                    title: "\(name)",
                    subtitle: "\(artistName)",
                    image: .init(data: coverArtData)
                )   
            }   
            
            static let defaultQuery = AlbumEntityQuery()
            
            static var typeDisplayRepresentation: TypeDisplayRepresentation { "Album" }
        }   
        
        struct AlbumEntityQuery: EntityQuery {
            @Dependency var catalog: AlbumCatalog
            func entities(for identifiers: [String]) async throws -> [AlbumEntity] {
                catalog.albums(for: identifiers)
            }
        }
    • 5:39 - Adopt IntentValueQuery to return results

      // Adopt IntentValueQuery to return visual search results
        import AppIntents
        import VisualIntelligence
        
        struct SearchHandler: IntentValueQuery {
            @Dependency var catalog: AlbumCatalog
            @Dependency var concertFinder: ConcertFinder
            
            func values(for input: SemanticContentDescriptor) async throws -> [VisualSearchResult] {
                guard let pixelBuffer = input.pixelBuffer else {
                    return []
                }   
                
                let albums = try await catalog.search(matching: pixelBuffer)
                
                return albums.map { VisualSearchResult.album($0) }
            }
        }
    • 6:24 - Build a catalog of albums with precomputed feature prints

      // Build a catalog of albums with precomputed feature prints
        import Vision
        
        @Observable
        class AlbumCatalog {
            static let shared = AlbumCatalog()
            
            struct CatalogEntry: Sendable {
                let album: AlbumEntity
                let featurePrint: FeaturePrintObservation
            }   
            
            private(set) var entries: [CatalogEntry] = []
            
            private func generateFeaturePrint(
                for image: CGImage
            ) async throws -> FeaturePrintObservation {
                let request = GenerateImageFeaturePrintRequest()
                let result = try await request.perform(on: image)
                return result
            }
        }
    • 6:45 - Search the catalog for albums matching the captured image

      // Search the catalog for albums matching the captured image
        func search(matching pixelBuffer: CVReadOnlyPixelBuffer, limit: Int = 10, maxDistance: Double = 1.0) async throws ->
        [AlbumEntity] {
            var cgImage: CGImage?
            _ = pixelBuffer.withUnsafeBuffer { VTCreateCGImageFromCVPixelBuffer($0, options: nil, imageOut: &cgImage) }
            guard let cgImage else { return [] }
            
            let queryPrint = try await generateFeaturePrint(for: cgImage)
            
            return try entries.compactMap { entry -> (album: AlbumEntity, distance: Double)? in
                let distance = try queryPrint.distance(to: entry.featurePrint)
                guard distance <= maxDistance else { return nil }
                return (entry.album, distance)
            }   
            .sorted { $0.distance < $1.distance }
            .prefix(limit)
            .map { $0.album }
        }
    • 8:27 - Create an open intent to land users on the right screen

      // Create an open intent to land users on the right screen
        import AppIntents
        
        struct OpenAlbumIntent: OpenIntent {
            static let title: LocalizedStringResource = "Open Album"
            
            @Parameter(title: "Album")
            var target: AlbumEntity
            
            @Dependency var appState: AppState
            
            func perform() async throws -> some IntentResult {
                await appState.openAlbum(id: target.id)
                return .result()
            }
        }
    • 12:05 - Use UnionValue to return multiple visual search result types

      // Use UnionValue to return multiple visual search result types
        @UnionValue
        enum VisualSearchResult {
            case album(AlbumEntity)
            case concert(ConcertEntity)
        }   
        
        struct OpenConcertIntent: OpenIntent {
            static let title: LocalizedStringResource = "Open Concert"
            
            @Parameter(title: "Concert")
            var target: ConcertEntity
            
            @Dependency var appState: AppState
            
            func perform() async throws -> some IntentResult {
                await appState.openConcert(id: target.id)
                return .result()
            }
        }
    • 12:18 - Expand the IntentValueQuery to return the UnionValue

      // Expand the IntentValueQuery to return the UnionValue
        struct SearchHandler: IntentValueQuery {
            @Dependency var catalog: AlbumCatalog
            @Dependency var concertFinder: ConcertFinder
            
            func values(for input: SemanticContentDescriptor) async throws -> [VisualSearchResult] {
                guard let pixelBuffer = input.pixelBuffer else {
                    return []
                }   
                
                let albums = try await catalog.search(matching: pixelBuffer)
                
                let artists = albums.map { $0.artistName }
                
                let concerts = await concertFinder.findNearby(byArtists: artists)
      
                return albums.map { VisualSearchResult.album($0) }
                    + concerts.map { VisualSearchResult.concert($0) }
            }
        }
    • 13:13 - Provide a link to in-app search

      // Provide a link to in-app search
        @AppIntent(schema: .visualIntelligence.semanticContentSearch)
        struct SemanticContentSearchIntent: AppIntent {
            static let title: LocalizedStringResource = "Search in app"
            static let openAppWhenRun: Bool = true
            
            var semanticContent: SemanticContentDescriptor
            @Dependency var catalog: AlbumCatalog
            @Dependency var concertFinder: ConcertFinder
            @Dependency var appState: AppState
            
            func perform() async throws -> some IntentResult {
                guard let pixelBuffer = semanticContent.pixelBuffer else { return .result() }
                let albums = try await catalog.search(matching: pixelBuffer)
                let artists = albums.map { $0.artistName }
                let concerts = await concertFinder.findNearby(byArtists: artists)
                await appState.openSearch(albums: albums, concerts: concerts)
                return .result()
            }   
        }
    • 15:24 - Request calendar access and fetch upcoming concerts

      // Request calendar access and fetch upcoming concerts
        import EventKit
        
        @Observable
        class UpcomingConcertManager {
            private let eventStore = EKEventStore()
            var upcomingConcerts: [EKEvent] = []
            var authorizationStatus: EKAuthorizationStatus = .notDetermined
            
            func requestAccessAndFetch() async throws {
                let granted = try await eventStore.requestFullAccessToEvents()
                guard granted else {
                    authorizationStatus = .denied
                    return
                }   
                authorizationStatus = .fullAccess
                await fetchUpcomingConcerts()
      
                // ...
            }
        }
    • 15:42 - Filter for upcoming events that match known artists in our catalog

      // Filter for upcoming events that match known artists in our catalog
        class UpcomingConcertManager {
            func fetchUpcomingConcerts() async {
                let predicate = eventStore.predicateForEvents(
                    withStart: .now,
                    end: .now.addingTimeInterval(90 * 24 * 60 * 60),
                    calendars: nil
                )   
                
                let events = eventStore.events(matching: predicate)
                
                upcomingConcerts = events.filter { event in
                    AlbumCatalog.shared.entries.contains { entry in
                        event.title?.localizedCaseInsensitiveContains(entry.album.artistName) == true
                    }
                }
            }
        }
    • 15:44 - Observe newly created events

      // Observe newly created events
        @Observable
        class UpcomingConcertManager {
            // ...
      
            func requestAccessAndFetch() async throws {
                // ...
      
                for await _ in NotificationCenter.default
                    .notifications(
                        named: .EKEventStoreChanged
                    ) {
                    await fetchUpcomingConcerts()
                }
            }
        }
    • 0:07 - Introduction
    • Visual Intelligence integration and what's new in iOS 26, iPadOS, and macOS, using a sample music-discovery app built throughout the session. Outlines the agenda: defining content, implementing a query, cross-platform adoption, and system store integrations.

    • 2:02 - Defining your content
    • Model your app's content as an AppEntity so Visual Intelligence can display it in search results. Covers the entity's DisplayRepresentation (title, subtitle, thumbnail) and best practices around concise identifying text and thumbnail-sized images.

    • 5:03 - Implementing a query
    • IntentValueQuery returns results from a SemanticContentDescriptor's pixel buffer — using the Vision framework's GenerateImageFeaturePrintRequest for on-device image similarity, with pre-computed feature prints and distance thresholds to keep results fast.

    • 8:18 - Opening results
    • Implement an OpenIntent to take people straight to the selected content. Keep it lightweight since it runs as the app foregrounds, and reuse an existing OpenIntent rather than creating one specific to Visual Intelligence.

    • 10:03 - Mac and iPad adoption
    • The same entities, query, and OpenIntent carry over to iPadOS and macOS with minimal changes. Account for platform differences such as camera versus screenshot input and the much larger pixel buffers on Mac that may need resizing.

    • 12:27 - Returning multiple result types
    • The @UnionValue type returns more than one entity type from a single query — here albums plus nearby concerts — encouraging you to derive related content rather than only matching pixels.

    • 12:56 - Continuing search in your app
    • The semanticContentSearch schema lets people continue into your full in-app search — pre-populating results from the captured context so they land on filters, categories, and deeper content.

    • 14:27 - System store integrations
    • Visual Intelligence can also write data your app reads back via system stores: events through EventKit (EKEventStore), contacts via CNContactStore, and medical-device readings via HealthKit (HKHealthStore). Observe store-change notifications so captured data appears automatically.

    • 17:16 - Next steps
    • Recaps the two integration points, Image Search and system stores, across iOS, iPadOS, and macOS. Points to documentation and related App Intents and Vision sessions.

Developer Footer

  • ビデオ
  • WWDC26
  • アプリにビジュアルインテリジェンスを統合するためのベストプラクティス
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • Apple Intelligence
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習とAI
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • Mini Apps Partner Program
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    最新ニュースを読む。
    Apple Developerアプリを入手する。
    Copyright © 2026 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン