WWDC Quick Look 💓 By SwiftGGTeam
What's new in Nearby Interaction

What's new in Nearby Interaction

元の動画を見る

ハイライト

Apple Location Technologies チームの Jon Schoenberg が、iOS 16 の Nearby Interaction フレームワークにおける 2 つの主要な新機能、ARKit 拡張モードとバックグラウンドセッションを紹介します。


主要内容

Nearby Interaction はもともと「近くのデバイスはどこにあるか」を解決していました。U1 チップと Ultra Wideband(UWB)測距に依存し、2 台のデバイス間、またはデバイスとアクセサリ間で距離と方向を取得します。2020 年に 2 台の iPhone をサポートし、2021 年に Apple Watch とサードパーティ UWB アクセサリに拡張しました。

このモデルは、ユーザーがスマートフォンを持って能動的にターゲットを探す場面に適しています。問題は 2 点あります。第一に、UWB の方向情報には視野角と遮蔽の制限があり、ユーザーが特定の角度に回ると安定した方向が取得できなくなることがあります。第二に、アプリがバックグラウンドに入るかユーザーが画面をロックすると、実行中の NISession が一時停止し、アクセサリがシームレスなインタラクションを続けられません。

iOS 16 の更新はこの 2 つの問題に対応します。Camera assistance は ARKit が計算したデバイスの軌跡を Nearby Interaction に渡し、有効視野を広げ、より安定した方向情報を生成します。Accessory background sessions は、Bluetooth LE でペアリングされた UWB アクセサリがアプリのバックグラウンド中も Nearby Interaction セッションを継続できるようにします。

セッションの博物館の例は具体的です。ユーザーが次の展示物を選択すると、アプリはその横の UWB アクセサリを発見し、左右にスマートフォンを振るよう促し、矢印を表示し、ターゲットが背後にあるか判断し、AR コンテンツを展示物の位置に重ねます。UWB、ARKit、Bluetooth、フォアグラウンド/バックグラウンド状態の調整は以前は開発者の仕事でした。Nearby Interaction が重要なパスをフレームワークに取り込みました。


詳細

ARKit 拡張モードを有効にする

04:47)アプリがすでに NIDiscoveryToken を受信し、設定を作成し、NISession を実行するフローを持っている場合、ARKit 拡張モードの有効化は NIConfiguration サブクラスで isCameraAssistanceEnabled を設定するだけです。Apple デバイス間、および Apple デバイスとサードパーティ UWB アクセサリ間の両方のインタラクションで動作します。

// 示意コード:session は完全なコードスニペットを提供していない。transcript で名指しされた API フローのみ示す。
let configuration = /* 既存フロー:NIDiscoveryToken で NIConfiguration サブクラスを作成 */
configuration.isCameraAssistanceEnabled = true

let session = NISession()
session.delegate = self
session.run(configuration)

キーポイント:

  • NIDiscoveryToken は nearby peer から取得し、アプリはそれを使って NIConfiguration サブクラスを作成します。
  • isCameraAssistanceEnabled は iOS 16 の新プロパティで、true に設定すると camera assistance が有効になります。
  • NISession は Nearby Interaction のセッション入口のままです。
  • run(configuration) でセッションを開始します。camera assistance によりフレームワークが内部 ARSession を自動作成・実行します。

05:27)フレームワークが作成する ARSession はアプリプロセス内で実行されるため、アプリは Info.plist にカメラ使用説明を提供する必要があります。この説明は、近くの物体を探すのにカメラが必要な理由をユーザーに伝えるべきです。

<!-- Info.plist:示意設定。アプリのシナリオに合わせて文言を変更する。 -->
<key>NSCameraUsageDescription</key>
<string>近くの物体の方向判断を改善し、空間ガイダンスを表示するためにカメラを使用します。</string>

キーポイント:

  • NSCameraUsageDescription はシステムのカメラ権限説明キーです。
  • camera assistance は ARKit を使用するため、カメラ権限要求がトリガーされます。
  • 説明文は「近くの物体を探す」と「カメラ」の関係を説明し、権限ダイアログでユーザーが混乱しないようにします。

既存の ARKit 体験と ARSession を共有する

06:19)アプリは同時に 1 つの ARSession しか実行できません。アプリがすでに ARKit 体験を持っている場合、Nearby Interaction が 2 つ目のセッションを自動作成することはできません。NISession.run の前に新しい setARSession を呼び出し、自分で作成した ARSession を Nearby Interaction に渡します。

// 示意コード:SwiftUI/ARView シナリオで基盤 ARSession を共有する。
let niSession = NISession()
let arSession = arView.session

niSession.setARSession(arSession)
niSession.run(configuration)

キーポイント:

  • arView.session は既存 ARKit ビューの基盤 ARSession を表します。
  • setARSessionNISession.run の前に呼び出す必要があります。
  • 呼び出し後、Nearby Interaction は内部 ARSession を自動作成しません。
  • ARKit 画面と Nearby Interaction の camera assistance が同じ軌跡データソースを共有できます。

07:16ARSession を直接管理する場合、Apple は ARWorldTrackingConfiguration で実行し、指定どおりに設定することを要求します。worldAlignmentgravity、collaboration と user face tracking は無効、initialWorldMapnil、delegate の sessionShouldAttemptRelocalizationfalse を返します。

// 示意コード:transcript が明示的に要求した設定項目のみ列挙。
let arConfiguration = ARWorldTrackingConfiguration()
arConfiguration.worldAlignment = .gravity
arConfiguration.isCollaborationEnabled = false
arConfiguration.userFaceTrackingEnabled = false
arConfiguration.initialWorldMap = nil

arSession.run(arConfiguration)

キーポイント:

  • ARWorldTrackingConfiguration は ARSession 共有時の実行設定です。
  • .gravity は世界座標を重力方向に整列します。
  • collaboration と user face tracking は無効にする必要があります。
  • initialWorldMapnil である必要があります。
  • 設定が要件を満たさない場合、NISessionDelegatedidInvalidateWith は新しい NIError.invalidARConfiguration を受け取ります。

新しい空間出力プロパティを使用する

08:21)アプリは引き続き NISessionDelegatedidUpdateNearbyObjects で nearby object の更新を受信します。camera assistance を有効にすると、NINearbyObject に 2 つの新プロパティが追加されます。horizontalAngleverticalDirectionEstimate です。既存の distance と direction と合わせて、デバイスと近くの物体の空間関係を記述します。

// 示意コード:transcript で言及されたオプション空間プロパティを処理する。
func session(_ session: NISession, didUpdate nearbyObjects: [NINearbyObject]) {
    guard let object = nearbyObjects.first else { return }

    // distance はメートル単位の距離表示に使える。
    let distance = object.distance

    // direction は 3D 指向に使える;利用不可時は horizontalAngle にフォールバック。
    let direction = object.direction
    let horizontalAngle = object.horizontalAngle

    // verticalDirectionEstimate を使う前に unknown を除外する。
    let vertical = object.verticalDirectionEstimate
}

キーポイント:

  • distance はメートル単位で、transcript はユーザーデバイスと近くの物体の主要な空間関係の一つと定義しています。
  • direction は現在のデバイスから近くの物体への 3D ベクトルで、nil の場合があります。
  • horizontalAngle は水平面上の 1D ラジアン角で、3D direction が解決できない場合でも利用可能なことがあります。
  • verticalDirectionEstimate は定性的な垂直関係で、same、above、below、aboveOrBelow、unknown のいずれかです。
  • verticalDirectionEstimate を使う前に unknown を確認し、不確実な状態を階層ガイダンスとして表示しないでください。

近くの物体を AR 世界に配置する

11:39)iOS 16 は NISessionworldTransform ヘルパーを追加しました。ARKit 座標空間での transform を返し、物理環境における nearby object の位置を表します。セッションデモで展示物の位置に浮かぶ球体は、これを使って AR コンテンツを配置しています。

// 示意コード:worldTransform で AR コンテンツを配置する。
if let transform = niSession.worldTransform(for: nearbyObject) {
    // transform に対応する位置に AR マーカーを配置する。
} else {
    // ユーザーに水平・垂直方向へデバイスを振るよう促す。
}

キーポイント:

  • worldTransformNISession の新しいヘルパーメソッドです。
  • 戻り値は ARKit の座標空間にあります。
  • transform が利用不可のときは nil を返します。
  • camera assistance が利用可能な transform に収束するには、ユーザーが水平・垂直方向に十分振る必要があります。
  • transform が体験に重要な場合、セッションはユーザーにアクションを促すことを推奨しています。

アルゴリズム収束状態でユーザーをガイドする

13:11horizontalAngleverticalDirectionEstimateworldTransform が一時的に利用できない理由をアプリが説明できるよう、NISessionDelegatedidUpdateAlgorithmConvergence が追加されました。NIAlgorithmConvergence とオプションの NINearbyObject を返します。この delegate は camera assistance が有効な場合にのみ呼び出されます。

// 示意コード:収束状態に基づいてユーザーにプロンプトを表示する。
func session(_ session: NISession,
             didUpdateAlgorithmConvergence convergence: NIAlgorithmConvergence,
             for nearbyObject: NINearbyObject?) {
    switch convergence.status {
    case .converged:
        showReadyState()
    case .unknown:
        showPreparingState()
    case .notConverged(let reasons):
        showGuidance(for: reasons)
    }
}

キーポイント:

  • NIAlgorithmConvergence には status プロパティがあります。
  • statusNIAlgorithmConvergenceStatus で、アルゴリズムが収束したかを表します。
  • nearbyObjectnil のとき、収束状態はセッション全体に属します。非 nil のときは特定の物体に対応します。
  • notConverged には reasons 配列が付き、アプリは理由ごとにアクションプロンプトを提供できます。
  • 理由には総運動不足、水平スイープ不足、垂直スイープ不足、照明不足が含まれる場合があります。
  • 複数の理由が同時に存在できます。セッションはアプリの必要に応じた順序でユーザーをガイドすることを推奨しています。

デバイス能力に応じて体験を調整する

16:23)従来の NISession.isSupported はデバイスが Nearby Interaction をサポートするかどうかのみを答えていました。iOS 16 は NISession.deviceCapabilities を追加し、NIDeviceCapability を返して、アプリが精密測距、方向測定、camera assistance を個別に確認できるようにしました。

// 示意コード:能力に応じて UI を選択する。
let capabilities = NISession.deviceCapabilities

guard capabilities.supportsPreciseDistanceMeasurement else {
    showUnsupportedState()
    return
}

if capabilities.supportsCameraAssistance {
    enableARGuidanceMode()
} else if capabilities.supportsDirectionMeasurement {
    enableDirectionOnlyMode()
} else {
    enableDistanceOnlyMode()
}

キーポイント:

  • NISession.deviceCapabilitiesisSupported のみを確認する方法に代わります。
  • supportsPreciseDistanceMeasurement は少なくとも旧来のサポート性チェックと同等です。
  • supportsDirectionMeasurement はデバイスが方向測定を提供できるかを示します。
  • supportsCameraAssistance はデバイスが ARKit 拡張モードをサポートするかを示します。
  • セッションは Apple Watch をサポートするため distance-only 体験を維持することを特に注意喚起しています。

バックグラウンドでアクセサリセッションを実行する

18:03)以前はアプリがバックグラウンドに入るかユーザーが画面をロックすると、実行中の NISession が一時停止していました。iOS 16 の accessory background sessions は、Core Bluetooth のバックグラウンド機能を使い、Bluetooth LE でペアリングされた UWB アクセサリと Nearby Interaction セッションを開始・継続できます。

概念フロー:
1. アクセサリから Ultra Wideband configuration data を受信する。
2. ペアリング済み Bluetooth LE 接続からそのアクセサリの Bluetooth peer identifier を取得する。
3. 両方のデータで NINearbyAccessoryConfiguration を作成する。
4. この設定で NISession を実行する。

キーポイント:

  • Ultra Wideband configuration data はアクセサリがデータチャネル経由でアプリに送る設定データです。
  • Bluetooth peer identifier はペアリング済み Bluetooth LE アクセサリから取得します。
  • transcript は新しい initializer が UWB configuration data と Bluetooth peer identifier の 2 つのデータを受け取ることのみ説明しており、Swift のパラメータラベルは示されていません。
  • アクセサリはすでに Bluetooth LE でペアリングされている必要があります。
  • アクセサリは新しい Nearby Interaction GATT service も実装し、iOS が Bluetooth identifier と UWB configuration の関連を検証できるようにする必要があります。

22:15)Nearby Interaction GATT service には暗号化 characteristic である Accessory Configuration Data があります。同じ UWB configuration data を含みます。アプリはこの characteristic を直接読み取れません。iOS はアクセサリの Bluetooth 身元と Nearby Interaction セッションが一致するかを検証するために使います。

// 示意コード:バックグラウンドセッションに必要なアプリ設定。
// Info.plist UIBackgroundModes:
// - nearby-interaction
// - bluetooth-central

キーポイント:

  • nearby-interaction はセッションで言及された Nearby Interaction バックグラウンドモードに対応します。
  • bluetooth-central は Xcode の「Uses Bluetooth LE accessories」機能に対応します。
  • アプリはバックグラウンドでアクセサリに接続できる必要があるため、Core Bluetooth のバックグラウンド接続と状態復元フローを実装します。
  • LE ペアリングのトリガーはユーザー確認ダイアログを表示するため、セッションはセットアップフローやユーザーが明示的にインタラクションしたい瞬間に置くことを推奨しています。

25:35)バックグラウンドセッションには重要な制限があります。アプリはバックグラウンド中に didUpdateNearbyObjects コールバックを受信せず、実行時間も得られません。NISession は継続実行され、UWB measurements はアクセサリに到達します。したがってバックグラウンドアクションは測定結果に基づいてアクセサリ側で実行する必要があります。

// 示意フロー:バックグラウンド中はアクセサリが UWB measurements を消費する。
// App: バックグラウンド NISession を確立し、共有可能な設定をアクセサリに送る。
// Accessory: UWB measurements を受信する。
// Accessory: 距離や方向に基づいてアクションをトリガーする(点灯、音楽再生、eBike のアンロックなど)。
// App: 重要なインタラクション時のみアクセサリから起動される(通知表示など)。

キーポイント:

  • アプリがバックグラウンドの間、NISession は一時停止しません。
  • アプリがバックグラウンドの間、didUpdateNearbyObjects はアプリにコールバックされません。
  • アクセサリは UWB measurements を受信し、ユーザーアクションを直接決定すべきです。
  • 省電力のため、セッションは重要なユーザーインタラクション時のみアクセサリからアプリへデータを送ることを推奨しています。

重要ポイント

  • やること:博物館や展示場の展示物ナビゲーション。 価値がある理由: camera assistance により距離、方向、水平角、垂直関係がより安定し、静止物体への誘導に適しています。 始め方: 各展示物に UWB アクセサリを配置し、アプリで isCameraAssistanceEnabled を有効にし、horizontalAngle で矢印を描き、worldTransform で AR マーカーを配置します。

  • やること:複数階層の物体探索アプリ。 価値がある理由: verticalDirectionEstimate は same、above、below、aboveOrBelow などの階層レベルのヒントを提供し、距離のみより室内探索に適しています。 始め方: didUpdateNearbyObjectsdistanceverticalDirectionEstimate の両方を読み取り、まず階層関係を促し、その後水平ナビゲーションを表示します。

  • やること:スマートスピーカーの入室時自動再生。 価値がある理由: accessory background sessions により UWB アクセサリがアプリのバックグラウンド中も測定を受信し続け、ハンズフリーに適しています。 始め方: スピーカーを Bluetooth LE でペアリングし、Nearby Interaction GATT service を実装し、新しい NINearbyAccessoryConfiguration initializer で UWB データと CBPeripheral.identifier をバインドし、アクセサリ側で測定を処理します。

  • やること:電動自転車の近接アンロック。 価値がある理由: ユーザーはアプリを開く必要がなく、アクセサリがバックグラウンドセッションの UWB measurements から本当に近づいているか判断できます。 始め方: アプリはペアリング、バックグラウンド接続、セッション設定を担当し、自転車側が測定に基づいてアンロックを実行し、ユーザーへのプロンプトが必要なときのみアプリに通知します。

  • やること:能力適応型の空間インタラクション UI。 価値がある理由: すべてのデバイスが方向測定や camera assistance をサポートするわけではなく、Apple Watch には distance-only 体験が依然必要です。 始め方: 起動前に NISession.deviceCapabilities を読み取り、supportsCameraAssistancesupportsDirectionMeasurementsupportsPreciseDistanceMeasurement に基づいて AR ガイダンス、方向ガイダンス、距離のみモードを選択します。


関連セッション

コメント

GitHub Issues · utterances