
-
SwiftUIによるvisionOSのシーンの設定
visionOSアプリのウインドウ、ボリューム、イマーシブ空間を強化する、エキサイティングな新しいAPIを紹介します。再起動やロックされた場合にシーンの動作を微調整したり、クリッピングマージンやスナップ機能を使ってボリュームを周囲に適応させたりすることが可能です。イマーシブなコンテンツをMacからVision Proにストリーミングすることもできます。ボリュームとイマーシブ空間を活用して、UIKitベースの既存のアプリを向上させましょう。
関連する章
- 0:00 - イントロダクション
- 2:11 - 起動とロック
- 8:15 - ボリュメトリックの機能強化
- 15:58 - イマーシブ空間
- 22:16 - シーンブリッジング
- 24:01 - 次のステップ
リソース
- Adopting best practices for persistent UI
- Canyon Crosser: Building a volumetric hike-planning app
- Petite Asteroids: Building a volumetric visionOS game
- Tracking accessories in volumetric windows
関連ビデオ
WWDC25
-
このビデオを検索
こんにちは Miguelです SwiftUIチームのエンジニアです このビデオでは visionOS 26に追加されたシーンの 素晴らしい新機能を いくつかご紹介します そして 私たち自身のシーンを どのように演出するかも学ぶかもしれません
visionOSの3つのシーンタイプは ウインドウ ボリューム イマーシブ空間です アプリでは この3つを組み合わせることで 独自の魅力的な体験を創出できます
本日は 3つのタイプすべてに適用される 新しいAPIと ボリュームとイマーシブ空間に重点を置いた いくつかのAPIについて説明します 友人のMaks、Amanda、Trevorが BOTanistの 魅力的な改良に取り組んでいます 空中庭園でロボットが美しい植物を 育てるのを手伝うゲームです
私自身は シーンの構築や装飾をとおして アプリに取り組んできました ロボット君がシェイクスピアの キャラクターに生命を吹き込み 演技の世界に挑戦するのを 手助けしてきました
アプリを開くと ステージ選択画面が 表示されます 新しいステージを作成します
これで BOTanistを動かして シーンを設定できます ステージのいたるところに移動できます
これで ロボット君が お気に入りの演劇を再現できます まるで「ロボとジュリエット」です
新しいシーンAPIでアプリを 改善する方法を見てみましょう visionOS 26の新しいシーンAPIです
最初に 新しいライフサイクルAPIについて 説明します ウインドウを起動して ルームに 固定するときの動作を定義します
次に 新しいボリュメトリックの 機能強化について紹介します ユーザーの環境に合わせて調整できます
そして RemoteImmersiveSpaceを 追加して macOSアプリから Apple Vision Proの シーンをプレビューします
既存のUIKitアプリに対しては 新しいシーンブリッジAPIを使って これらの驚くべき立体的で没入感のある 体験を追加して締めくくります
最初に 起動と固定について説明します
visionOS 26では いくつかの macOS ライフサイクルAPIが導入されました これは非常に便利です シーンの復元とアプリの起動を 管理するAPIについて説明します 固有のウインドウを作成する APIについても説明します
visionOS 26では ウィンドウやボリューム さらには 新しいウィジェットを特定の部屋に固定して 物理的な環境に保持できるようになりました
これにより バーチャルコンテンツは その空間により存在感を持つようになります これらの固定されたウインドウは 使用された部屋に結び付けられます
後でその部屋に戻ると ウインドウが再び表示されます
固定機能によるシーン復元は 素晴らしいです すべてのウインドウを残しておき いつでも戻ってくることができます
一般的に ユーザーはすべてのウィンドウを 固定できることを期待し システムがそれを復元することを望みます そのため ほとんどのシーンで復元を優先してください システムが自動的にこれを行います
ただし いくつかのウィンドウは この方法で保持するのが 適切でない場合もあります
ウェルカム画面や 特定のアプリ状態に結びついた ツールウィンドウ ログインプロンプトのような 一時的な要素では シーン復元を無効にすることを 検討してください
アプリにイマーシブモードを追加したので お気に入りのロボットの動きを 十分に楽しむことができます ツールバーは 前方の独立した ツールウインドウに分離され イマーシブな状態でも 簡単に ステージコントロールにアクセスできます
イマーシブ空間は復元されないことに 注意してください
したがって この部屋に戻ってきたとき イマーシブ空間は復元されません
ただし 誰かがツールウィンドウを 固定していた場合 単独で 何もない状態で 表示されることになります
この予期しない状態を回避するには restorationBehavior(.disabled) 修飾子を WindowGroupに追加します これによりツールウィンドウが 復元および固定されなくなります
これで 後でこの部屋に戻ったときに 余分なウィンドウは戻りません
アプリを起動すると 最初のウィンドウが 表示され 新しいスタートとなります
UIKitでは 新しい destructionConditions APIの .systemDisconnectionプロパティを 使用してUIシーンの復元を無効にできます 詳しくはドキュメントをご覧ください
場合によっては アプリが開始するシーンを 動的に変更することで メリットが得られることがあります
例えば アプリの初回起動時に ステージ選択の前に 挨拶するウェルカムウィンドウを 追加したいと考えています
アプリの状態に基づいて 起動時に表示する ウインドウをカスタマイズするには defaultLaunchBehavior修飾子を 使用します
ここではアプリの初回起動時に ウェルカムウィンドウを 表示するように優先します
そのウィンドウが表示されたら 値をオフに切り替えることができます もうそのウィンドウを表示する 必要はありません
選択した起動ウインドウの役割は Info.plistの Application Scene Manifestの 希望するデフォルトシーンセッションの役割 プロパティと一致している必要があります
つまりデフォルトのシーンセッションの 役割をウィンドウに設定すると アプリ起動時にシステムが 通常のウィンドウシーンのみを考慮します
その場合defaultLaunchBehaviorで 優先しようとしても ボリュームは無視されます そのため 希望するシーンを そのセッションの役割と一致させてください
defaultLaunchBehavior修飾子には もう一つ便利な機能があります
部屋に戻ったときにツールパネルが 再表示されないようにしたいことと それを修正するために restorationBehaviorを 使えることについて話しました こちらでも似たような問題があります
今のところ Crownを押して イマーシブ空間を解除し ツールウィンドウを閉じても
アプリを再起動すると このウィンドウが再表示されます
これにより 復元機能がある場合と同じような 予期しない状態になります
代わりに ステージ作成ウィンドウから始めて 安全な状態でアプリを再開したいです
これを行うにはdefaultLaunchBehavior (.suppressed)修飾子を ツールウインドウに追加します これにより ホームビューから アプリを再起動するときに このウィンドウを再表示しないように システムに指示します
一般的に 予期しない状態に陥るのを避けるために セカンダリーシーンには defaultLaunchBehavior (.suppressed)を使用します
UIKitではUISceneの destructionConditionsに userInitiatedDismissalオプションを 追加することで 同じ動作を実現できます
visionOS 26では 独自のウィンドウの 作成もサポートしています
これらは複製できないウインドウです 一度に1つの一意のインスタンスしか 存在できません
Macと同様 WindowGroupではなく Window APIを使用して 宣言します
ゲームウィンドウやビデオ通話のような 重要なインターフェースの重複を 防ぐためにこれらを使用してください
また 1つ以上のインスタンスを 必要としない 補助的な機能を提供するために 使用してください
ウェルカムウインドウには 複数のインスタンスは必要ありません そのため 独自のウインドウに置き換えます
ただし メインステージのボリュームは 複数のステージを同時に作成できるように WindowGroupとして保持します
すばらしい アプリのライフサイクルは これまでで最高です 固定時やアプリ起動時に表示される ウィンドウをカスタマイズしました そして 必要に応じてウィンドウを 独自に保つようにしました
visionOS 26には ボリュームをさらに深めるための 多くの新しい強化機能があります
新しい平面へのスナップ機能 表示機能の強化 および Clipping Margins API について話します
では 早速始めましょう
visionOS 26の新機能では ウィンドウやボリュームを 物理的環境にスナップできます ウィンドウを表面に近づけるだけで スナップできます 復元可能なウインドウの場合 これでウィンドウを固定して保持できます
ウィンドウの背面を 壁のような垂直面にスナップできます ボリュームの底面を床やテーブルのような 水平面にスナップすることもできます
visionOS 26の新機能のウィジェットは どちらの種類にもスナップできます
visionOSアプリにウィジェットを 追加する方法について詳しくは 「What’s new in widgets」を ご参照ください
ウィンドウやボリュームでは スナッピングイベントに関する 情報も取得できます
アプリでは ボリュームをテーブルにスナップして 水平に固定できます
これは第一歩ですが 空間におけるステージを より存在感のあるものにしたいと思います ボリュームがテーブルにスナップされたとき ロボットを直接テーブルに 立たせたいと思います
スナッブ状態に関する情報を取得するには 新しい SurfaceSnappingInfo APIを使います
このAPIは ウィンドウの一般的な スナップ状態を判断するための 簡単なisSnappedプロパティを 提供します
より高度なユースケースでは スナップサーフェスの ARKit分類を取得できます この詳細レベルには ユーザーの許可が必要です その方法を説明します
詳細なスナップサーフェス情報を 有効にするには まず Application Wants Detailed Surface InfoキーをYESに設定し Privacy World-Sensing Usage-Descriptionキーには 許可を求める際に表示する 説明を設定する必要があります
これら2つのキーは アプリのInfo.plistで設定できます
それが終わったらコードに取り掛かれます
ここで 環境からsurfaceSnappingInfoを 取得します
onChangeの中で シーンが現在 スナップされているかどうかを確認します そしてスナップ面の分類に アクセスする権限があるかを確認します
authorizationStatusを確認ことで 必要に応じて 自動的に許可を求めます
ここで テーブルにスナップされたとき ステージの下のプラットフォームを 隠したとします これを管理するために状態変数を使用します
これらの変更により ボリュームをテーブルにスナップさせ ロボットが自分の環境で 存分に動作できます 素晴らしいですね
また テーブルの周りを歩くと邪魔になる 壁が隠れるようにしたので 常にボリュームの中を見ることができます
これはonVolumeViewpointChange 修飾子を使用して シーンの視点の変化に反応することで 行いました
OwenがどのようにBOTanistに 追加したかは WWDC24の「Dive deep into volumes and immersive spaces」で 詳しくご確認ください
また ステージの周りに 新しい小道具を配置できるようにしたいです ボリュームのツールバーに様々な小道具を 追加できるポップオーバーを追加できます
いいですねようやく『The Tragedy of King Gear』を再現できます
以前は 表示は Windowsでのみ サポートされていました
visionOS 2.4で ネストされた表示の サポートが追加され シートから表示されるポップオーバーや オーナメントから表示される コンテキスト メニューなどが可能になりました
visionOS 26では プレゼンテーションに まったく新しいソースが加わりました これで ボリューム内や ボリュームのオーナメントから RealityViewsへのアタッチメント またはRealityKitの PresentationComponentを使用して 直接プレゼンテーションができます
アタッチメントと PresentationComponentを使った RealityKitでのプレゼンテーションについて 詳しくは 「Better Together: SwiftUI and RealityKit」をご参照ください
これは 小さなサブセットに限定されません すべての表示タイプが利用可能です メニュー ツールチップ ポップオーバー シート アラート 確認ダイアログなどです
これらのプレゼンテーションをSwiftUIで 作成する方法については ドキュメントを確認してください
これらのプレゼンテーションはすべて 3Dコンテンツによって 隠されても見えるように 特別な視覚処理が施されています
デフォルトでは 遮るコンテンツと さりげなくブレンドします
ただし これは遮るコンテンツを 目立って突破するか その背後に隠れるように カスタマイズできます
これをカスタマイズするには subtle prominent none オプションを使用します
これらのオプションは presentationBreakthroughEffect 修飾子を使って適用できます
プレゼンテーション以外の要素には breakthroughEffect修飾子を使用して 同じ効果を得ることができます
プレゼンテーションにカスタムUIを 好きな場所に追加できるようになりました さらに追加してみます
ポップオーバーメニューを追加して 舞台装飾を変更します これで ロボット君を劇場から 南国の島に移動できます 『Tempest』にぴったりです
このセットは多くの可能性を秘めています しかし 何かアレンジを加えたいところです 滝はどうでしょうか 雷雲もいいかもしれません
それでも これらのものが アクションの核心を妨げないように 注意します これには 新しいクリッピングマージンを 使用します
ボリュームを使うと新しいpreferred WindowClippingMargins APIで シーンの境界外にコンテンツを レンダリングできます
このコンテンツは インタラクティブではありません したがって 視覚的な華やかさの ためだけに使用してください
このような境界は システムによって 許可されない可能性があります これに対応するには windowClippingMargins環境変数で windowClippingMargins環境変数を 使用します
実際に見てみましょう
preferredWindowClippingMargins APIで 希望するクリッピングマージンを指定できます ここでは 下部にマージンを設定したいです
maxWaterfallHeightを 1メートル単位で ポイントに変換するために PhysicalMetricから得た pointsPerMeter係数を掛けています
次にwindowClippingMargins 環境変数で 許可されたマージンを読み取ります
これにより 滝を拡大縮小して マージン内でレンダリングできます
許可されたものに関係なく 滝のモデル全体が常にレンダリング されるように マージンと 滝の高さの最小値を取ります
すると こうなります とても良くなりました 雲が良い嵐の雰囲気を加え 滝はベースプレートの下に レンダリングされます コンテンツを上にずらさずに 島と そこにいるロボットに 焦点を当て続けます
BOTanistが注油直後だといいですね
これで 私たちの最新の演劇作品は これまで以上にリアルに感じらます 平面へのスナップと クリッピングマージンにより コンテンツは 私たちの物理的な 空間に適応します プレゼンテーションを使って 完璧なシーンを作り上げるための 強力なインターフェースを作成できます
それでは アプリのイマーシブ体験を向上 させるために何ができるか見てみましょう
イマーシブ空間は 空間的な体験を 周囲にもたらします visionOS 26は イマーシブ空間で さらに多くのことを行うための 素晴らしい新しい方法をもたらします
ワールドリセンタリングイベントの イマーシブスタイルの新機能 macOS でのリモートイマーシブ空間 Metal によるレンダリングのための コンポジターベースのイマーシブ空間を紹介しましょう 自分の空間を移動するとき ユーザーはDigital Crownを長押して 周囲のアプリの体験を 再センタリングできます
アプリがARKitデータを使用する場合 保存しておいた位置情報が 無効になることがあります
新しいonWorldRecenterビュー 修飾子で ワールドリセンターリングイベントを聞く ことができ 通知を受けることができます
これは新しい座標系に基づいて 位置を再計算し保存するのに 非常に役立ちます
visionOS 26には イマーシブ空間に利用できる 様々な没入スタイルの 新しいカスタマイズも含まれています
段階的なイマーシブスタイルは イマーシブ空間を部分的に提示しながら 現実世界にユーザーを留めておく 素晴らしい方法です
イマーシブコンテンツは ポータル内に表示され Digital Crownを回すことで サイズを変更できます
この没入範囲は 段階的な イマーシブスタイルでカスタマイズできます
visionOS 26では このポータルの アスペクト比もカスタマイズできます 既存の横向きのアスペクト比 または新しい縦向きのアスペクト比を 使用できます
iPhoneゲームをApple Vision Proで プレイする場合や 多くの動きが含まれる体験には 縦向きのアスペクト比を検討してください 周囲が安定していることで ユーザーはより快適に感じることができます
このアスペクト比は 没入範囲と同様に段階的なスタイルの パラメータで指定できます
段階的なスタイルに加えて イマーシブ空間の 混合イマーシブスタイルにも 新しいカスタマイズがあります
イマーシブスタイルを mixedに設定すると イマーシブ空間のコンテンツは 周囲に溶け込みます
これはこのアプリのデフォルトスタイルです
visionOS 26ではイマーシブ空間の コンテンツがシステム環境とも融合できます つまり 月にいながらロボットの最新作を 観ることができます
これを可能にするために 共存動作を持つ immersiveEnvironmentBehavior シーン修飾子を使用してください
混合イマーシブ空間で ユーザーが現実世界の周囲を認識する 必要がない場合にこれを行ってください
アプリに追加した小道具を 気に入っていますが 新しいシーンを作成する際は 自分のモデルを持ち込みたいと 思っていることもわかっています これらのモデルはお気に入りの macOSアプリで作成されるかもしれません
これらのモデルをMacから 直接使用できるようにするために 同じステージ作成機能を備えたアプリを macOSに導入しました
より迅速な反復のために macOSからvisionOSにステージを 移行せずに 直接イマーシブ空間として シーンを プレビューできたらすごいですよね
visionOS 26とmacOS Tahoeは それを可能にする RemoteImmersiveSpacesを 追加します リモートイマーシブ空間を使用すると CompositorLayerでMetalを使って Macのアプリコードや リソースからコンテンツをレンダリングし
Vision Proでイマーシブ体験として 表示できます
アプリでこの機能を実際に見てみましょう
Macアプリで Metalを使用して 新しいイマーシブ空間を構築し ボタンを 追加しました
これをクリックすると ターゲットの Vision Proデバイスの選択を求められます
Vision Proで接続リクエストを 承認します
するとすぐに ImmersiSpaceが開き ロボットの最新ショーに追加した 新しい小道具を見ることができます
これを実現するために CompositorLayerを含む CompositorLayerが含まれています
これがvisionOSで表示され メインステージのような他のシーンは 引き続きMacで直接表示されます
CompositorLayerとARKitSessionを リモートVision Proデバイスに適応させる 方法について詳しくは 「What’s new in Metal rendering for immersive apps」をご覧ください
リモートイマーシブ空間で CompositorLayerを使用すると Metalを使ったイマーシブ体験を 作成するための多くの可能性が得られます
ただし CompositorLayerは ビューではないため ImmersiveContentなど ビューを 必要とするコンテキストでは使用できません
これまで 環境変数やView修飾子が CompositorLayerには 利用できないことを意味していました
visionOS 26では 新しいCompositor Contentビルダータイプが追加され CompositorLayerでSwiftUIの 全機能を使用できるようになりました
これにより 環境変数にアクセスしたり 修飾子を追加したり SwiftUIビューと同じように 状態変数を使用することもできます
CompositorContentは scenePhaseやopenWindowなど 多くの便利な環境変数と onImmersionChangeやonWorld Recenterなどの修飾子を提供します
これらにより CompositorLayerは リモートイマーシブ空間でも visionOSで直接動作する 通常の空間でも 強力に使用できるようになります
アプリのアップグレードにより CompositorContentを使用することは 使用可能なイマーシブ空間修飾子の 一部を見直し アプリにどのように適用できるかを見直す 素晴らしい方法となりました
以上がイマーシブ空間の新機能です 環境再センタリングイベント 新しいイマーシブスタイルのカスタマイズ RemoteImmersiveSpaceによる Macからのイマーシブ空間の創出 そしてCompositorContentについて 説明しました
これらの機能により アプリの見た目は 素晴らしいものになりました 実際 これらの素晴らしい ボリュメトリック体験を 他のアプリにも追加したいと思っています
ただし 一部のアプリはUIKitで 構築されており UIKitはボリュームや イマーシブ空間をサポートしていません しかし 今はシーンブリッジングによって それが可能になります
シーンブリッジングを使用すると 既存のUIKitアプリと 既存のUIKitアプリとイマーシブ空間を 統合できます
例えば Safariは SwiftUIビューを使用していますが UIKitライフサイクルで構築されています
Safariは新しい空間ブラウジング機能に シーンブリッジングをうまく活用しています
その方法を見てみましょう
SwiftUIのシーンをUIKitアプリに ブリッジするには まず UIHostingSceneDelegateを継承する クラスタイプを作成します
このタイプを使用して 使い慣れたのシーンボディ構文で rootSceneプロパティに SwiftUIシーンを宣言できます
これで 他のUIKitシーンと同様に UISceneSessionActivationRequestを 作成して このシーンをリクエストできます
この場合 シーンを宣言する ホスティングデリゲートクラスと 開きたいシーンのIDを渡します
あとは activateSceneSessionを使用して このリクエストを送信するだけです
configurationForConnectingで ホスティングデリゲートクラスを設定すると 外部イベントに対応することもできます
このAPIには 既存のmacOS AppKitアプリに SwiftUIシーンをブリッジするための 対応するAppKit APIも含まれています
このアプリは現在 visionOS 26の 新機能を最大限に活用しており 位置の固定 表面へのスナップ Macからのリモートオープンなどが 可能です 友達に見せるのが楽しみです
ご自身のアプリを見直して シーンを見直して 位置の固定と復元機能を 最大限に活用しているか確認してください
スナップやクリッピングマージンを使用して シーンを周囲に適応させることができます
そしてリモートイマーシブ空間を使って macOSアプリのコンテンツを Vision Proで没入させてください
幕は降りますが アプリでは1シーンずつ ショーが続きます ご視聴ありがとうございました
-
-
4:10 - Disabling restoration
// Disabling restoration WindowGroup("Tools", id: "tools") { ToolsView() } .restorationBehavior(.disabled)
-
4:36 - Disabling restoration in UIKit
// Disabling restoration windowScene.destructionConditions = [ .systemDisconnection ]
-
5:02 - Specifying launch window
// Specifying launch window @AppStorage("isFirstLaunch") private var isFirstLaunch = true var body: some Scene { WindowGroup("Stage Selection", id: "selection") { SelectionView() } WindowGroup("Welcome", id: "welcome") { WelcomeView() .onAppear { isFirstLaunch = false } } .defaultLaunchBehavior(isFirstLaunch ? .presented : .automatic) // ... }
-
6:39 - "suppressed" behavior
// "suppressed" behavior WindowGroup("Tools", id: "tools") { ToolsView() } .restorationBehavior(.disabled) .defaultLaunchBehavior(.suppressed)
-
7:44 - Unique window
// Unique window @AppStorage("isFirstLaunch") private var isFirstLaunch = true var body: some Scene { // ... Window("Welcome", id: "welcome") { WelcomeView() .onAppear { isFirstLaunch = false } } .defaultLaunchBehavior(isFirstLaunch ? .presented : .automatic) WindowGroup("Main Stage", id: "main") { StageView() } // ... }
-
10:24 - Surface snapping
// Surface snapping @Environment(\.surfaceSnappingInfo) private var snappingInfo @State private var hidePlatform = false var body: some View { RealityView { /* ... */ } .onChange(of: snappingInfo) { if snappingInfo.isSnapped && SurfaceSnappingInfo.authorizationStatus == .authorized { switch snappingInfo.classification { case .table: hidePlatform = true default: hidePlatform = false } } } }
-
14:41 - Clipping margins
// Clipping margins @Environment(\.windowClippingMargins) private var windowMargins @PhysicalMetric(from: .meters) private var pointsPerMeter = 1 var body: some View { RealityView { content in // ... waterfall = createWaterfallEntity() content.add(waterfall) } update: { content in waterfall.scale.y = Float(min( windowMargins.bottom / pointsPerMeter, maxWaterfallHeight)) // ... } .preferredWindowClippingMargins(.bottom, maxWaterfallHeight * pointsPerMeter) }
-
16:44 - World recenter
// World recenter var body: some View { RealityView { content in // ... } .onWorldRecenter { recomputePositions() } }
-
17:58 - Progressive immersion style
// Progressive immersion style @State private var selectedStyle: ImmersionStyle = .progressive var body: some Scene { ImmersiveSpace(id: "space") { ImmersiveView() } .immersionStyle( selection: $selectedStyle, in: .progressive(aspectRatio: .portrait)) }
-
18:37 - Mixed immersion style
// Mixed immersion style @State private var selectedStyle: ImmersionStyle = .progressive var body: some Scene { ImmersiveSpace(id: "space") { ImmersiveView() } .immersionStyle(selection: $selectedStyle, in: .mixed) .immersiveEnvironmentBehavior(.coexist) }
-
20:14 - Remote immersive space
// Remote immersive space // Presented on visionOS RemoteImmersiveSpace(id: "preview-space") { CompositorLayer(configuration: config) { /* ... */ } } // Presented on macOS WindowGroup("Main Stage", id: "main") { StageView() }
-
20:48 - 'CompositorLayer' is a 'CompositorContent'
// 'CompositorLayer' is a 'CompositorContent' struct ImmersiveContent: CompositorContent { @Environment(\.scenePhase) private var scenePhase var body: some CompositorContent { CompositorLayer { renderer in // ... } .onImmersionChange { oldImmersion, newImmersion in // ... } } }
-
23:00 - Scene bridging
// Scene bridging import UIKit import SwiftUI // Declare the scenes class MyHostingSceneDelegate: NSObject, UIHostingSceneDelegate { static var rootScene: some Scene { WindowGroup(id: "my-volume") { ContentView() } .windowStyle(.volumetric) } } // Create a request for the scene let requestWithId = UISceneSessionActivationRequest( hostingDelegateClass: MyHostingSceneDelegate.self, id: "my-volume")! // Send a request UIApplication.shared.activateSceneSession(for: requestWithId)
-