ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
UIKitにおける空間コンピューティングの概要
UIKitアプリをvisionOSで展開する方法を学びましょう。新しい実行先でビルドする方法、空間コンピューティング向けAPIの紹介とそのベストプラクティス、visionOSのUIKitでSwiftUIを使用したコンテンツを3次元に対応させる方法を解説します。
関連する章
- 1:35 - Getting started
- 2:56 - Platform differences
- 5:36 - Polishing your app
- 5:52 - Polish: Colors
- 10:20 - Polish: Hover
- 12:12 - Polish: Input
- 13:47 - Outside the bounds
- 15:03 - Outside: Presentations
- 17:11 - Outside: Ornaments
- 21:51 - Outside: RealityKit
リソース
関連ビデオ
WWDC23
-
ダウンロード
♪ ♪ ♪ Grace Kendall: 皆さんこんにちは “Meet UIKit for spatial computing”へようこそ UIKitチームのエンジニア Grace Kendallです 同僚のAndrewと一緒に 既存の UIKitアプリを全く新しい次元に引き上げる 方法についてお話しするのが楽しみです この新デバイスは 空間体験に 最適なプラットフォームで たくさんの新しい3D機能が導入されています さらに嬉しいのは 皆さんおなじみの UIフレームワークを使っていることです この動画は UIKitについて解説していきます SwiftUIについては “Meet SwiftUI for spatial computing”と “Elevate your windowed app for spatial computing”をご覧ください この動画では 新しい プラットフォーム向けのアプリを 構築する方法について ステップを追って説明します 次に 他のAppleのプラットフォームとは 異なるユニークな特徴と それらをどのようにコードで実装するべきかを 説明していきます またUIKitで導入された 新しいAPIを使って アプリを改善していきます 最後にUIKitに加えてSwiftUIを使い まったく新しい3D機能を 追加する方法を紹介します では始めましょう これはiOS用に書かれた ピクセルアートの アニメーションデモアプリで UIKitを使っています 私の親しい友達がこのアプリに 絵を提供してくれました iPadでの見た目や操作感も素晴らしく 多くのシステムコンポーネントや ダイナミックなアニメーションを駆使し Apple Pencilにも対応しています これを空間コンピューティングに 対応させましょう まず最初に XcodeプロジェクトのGeneralタブで 新しい実行先を追加します このアセットカタログで新しいアプリ アイコンを追加します なぜならこのプラットフォームの アイコンは特別だからです 3つの画像が重なっていて アプリアイコンを見ると動的に反応します チームメイトのJessicaは とても才能のあるアーティストです このアプリのために 新しいアイコンを用意してくれたので ここで追加しておきます
次に 新しいデバイスシミュレータを ターゲットに選択し ビルドします
ビルドエラーが発生しました iPadアプリで使われているAPIの一部は このプラットフォームでは 使用できないようです その理由を説明します このプラットフォームは 他のAppleのプラットフォームとは異なり まったく新しい機能と特徴を備えています そこで アプリ移行に際しての 注意点をいくつか紹介します 初めてアプリを移行する場合 以前のiOSバージョンで 非推奨となったAPIと このプラットフォームに うまく変換されないAPIの 2つの点について調べる必要があります このデバイスは iOS 14以前に 非推奨となった APIをサポートしていません 新プラットフォームへの移行は 非推奨APIの使用を見直し 共有コードベースをアップデートしましょう 最新かつ最高の技術を 採用する絶好の機会となっています また このプラットフォームに 変換されない APIのコレクションもあります UIDeviceOrientationがその一例です このAPIは デバイスが複数の向きで 使用されることを前提としていますが このデバイスでは当てはまりません また UIScreenは別の例です このデバイスでは 一つのハードウェアスクリーンによる 一つのウインドウという前提は成り立ちません また タブバーのデザインも大きく異なり 先頭や末尾というレイアウトがされないため leadingAccessoryViewと trailingAccessoryViewsは 利用できません デバイスにて適用できないが故に 利用できないAPIの例を 3つ挙げましたが この他にもまだあります 詳細については ドキュメントをご覧ください ではコードに戻って 何が問題だったのかを調べてみましょう このエラーを見てみましょう EditorViewController エクステンションの中に UIPencilInteractionがあります このデバイスはApple Pencilを サポートしていないので このAPIはこのプラットフォームで 利用できません コンパイルを通すために 条件分岐を入れて実行されないようにしましょう もう一度ビルドして実行しましょう
OKです! 起動したようですね アプリがShared Spaceで 動く様子を見ると ワクワクしますね ですがいくつか 改善できそうな点があるようです ではアプリをすべてチェックして 改善点を探してみましょう Simulatorでは マウスでクリックすると その場所にフォーカスをし 指をタップしている動作になります アプリでまず目につくのは 美しいガラスの背景です すべてのアートを見てみると アプリをインタラクティブに見せる ホバーの視覚効果があります 検索バーの見た目も変更され くぼんだ見た目になっています
異なるアートワークを開いて 心行くまでピクセル画を作れます ひとつ改善できそうなところは タイトルの黒いテキストと サブタイトルのグレーのテキストです iPadの白い背景では 黒のテキストはきれいに見えましたが ガラスの背景とは合っていないようです もう少しポップな感じでも良さそうです 検索バーの見た目と サイズ感がとても良いですね タイトルテキストも同じようにしたいです セマンティックカラーは新しくありませんが このプラットフォームでは有用です アプリの見た目がプラットフォームや 外観 そしてアクセシビリティ設定に 対応できるよう セマンティックのカラーや フォント 素材を選ぶことが重要です UIColor.labelのような設定は すべてが完璧に見える 新たな価値を提供します RGB値で色を定義する代わりに セマンティックカラーを使うと アプリがどのプラットフォームで 動作していても 見た目が 正しくなるよう システムが色を調整します 例えば システムシアンは iOS macOS watchOSで それぞれ色合いが微妙に異なります iPadでは これに加えて ダークモードにも 適応できる利点があります このプラットフォームでは systemBackgroundColorは ガラスの背景で使用すると デフォルトで鮮やかな色合いになります 同様に 固定フォントサイズを使う代わりに HeadlineやBodyのような セマンティックフォントスタイルで 使用すると読みやすくなります これはアクセシビリティの 観点からも正しいことです セマンティックフォントサイズは 読みやすさを確保するために Dynamic Typeで調整されます ここでは TextFieldのテキストと サブタイトルラベルの色は RGBで定義したUIColorsを使っています これらを使う代わりに プライマリおよびセカンダリラベルの セマンティックカラーを使いましょう これにより iPadでも見た目が良く このプラットフォームにも より合ったスタイルになります。 さらに セマンティックカラーを使用する すべてのUILabelsは デフォルトで鮮やかな色合いになります テキストフィールドのボーダースタイルを roundedRectに設定することもできます これにより くぼんだ感じの 見た目をつくれます そして ビルドして実行した結果… …とても良くなりましたね! ラベルは読みやすく テキストフィールドを使って アートの タイトルを編集できることも明確です 次に マテリアルについてお話します マテリアルはこのプラットフォームの大きな要です アプリを美しく見せ 周囲の一部であるように感じさせてくれます また どのような状況でも 文字を読みやすくしてくれます マテリアルは 照明の状況や背後にある 物体の色に応じて コントラストと カラーバランスを調整してくれます このため このプラットフォームでは ライトとダークの外観の区別がありません すべての組み込みコントロールとコンテナは デフォルトでVibrantな 素材を使用しており アプリが驚くほど美しく見えます アプリの背景となるガラス素材が とても素敵ですね これはすべてのUINavigationControllerと UISplitViewControllerに デフォルトで備わっています これにより 周囲の風景が 半透明で透過するようになります 新しいUIViewControllerの preferredContainer BackgroundStyleプロパティを 上書きして .automaticや.glass .hiddenを返すこともできます 次に アプリ内の一部のビューに カーソルを合わせると 薄くハイライトされて表示されます これはアプリのレスポンシブ性を高めます contorolsやlistsなどの システムコンポーネントを使うと デフォルトでこれらのホバーエフェクト マテリアルや鮮やかさなどを 得られるようになります ホバーエフェクトは インタラクティブ性を示します ビューにホバーエフェクトを追加すると ターゲットしやすくなります このプラットフォームで一つ重要なのは ユーザーの視線の情報については アプリのプロセスには決して 送信されないということです UIKitには ホバーエフェクトを追加 カスタマイズまた無効化できる 新しいAPIが用意されています UIViewにはHoverStyleという 新しいプロパティがあります 多くのインタラクティブ コンポーネントはcontrolsと同様 デフォルトでホバーエフェクトを持っています HoverStyleプロパティを設定し highlightやliftなどのプロパティを 指定することで ビューの hoverStyleをカスタマイズできます ホバーエフェクトを削除するには このプロパティをnilに設定します さらに 新しいUIShape APIを使って ホバーエフェクトの形状を指定することもできます コレクションビューのセルに ホバーエフェクトがあり それが気に入っているのですが 今回は角を丸くしたいと思います 丸みを帯びた長方形をホバー形状として 使用するには セルにhoverStyleプロパティを設定し 丸みを帯びた長方形の形状を 指定する必要があります こうすることで セルのホバー形状が角の立った長方形から… …丸い長方形になります テキストフィールドと背景の角が 丸くなったことで 見た目が良くなりました 各コレクションビューのセルを見ると ホバーの形状が丸くなりました
っそいて最後に見ておきたいのは 入力です このプラットフォームには コンテンツと やり取りする 新しい入力システムが導入されました 各要素を見て ピンチしたり、指を離す動作が TapGestureに匹敵します ピンチして 手を動かし 離すとPanGestureです アプリの近くにいれば 手を伸ばしてタッチすることもできます トラックパッドを接続すれば それを使ったシステムの操作も可能です さらにアクセシビリティテクノロジーも デバイスで使用可能です VoiceOverとSwitch Controlで 誰でも操作できます システムのジェスチャー認識機能は トラックパッドを含む すべての入力方式で動作します しかし このプラットフォームでは 片手ごとに1つのタッチしかできないため 同時入力は 最大2つであることに注意が必要です iPadアプリには 4本指でスワイプして 既存のアートを全削除し 新しく始めるという ジェスチャーがありました このジェスチャーは残しておきたいので このデバイスでは実行しないようにします 代わりに このコードを変更して ユーザーインターフェースの 種類を確認し .realityなら 必要なタッチ数を2回に設定します 変更が完了し アプリも洗練されてきました いよいよこのサンプルアプリを 次のレベルに引き上げる時です ここからは同僚のAndrewが 詳しく説明します Andrew: ありがとう Grace こんにちは UIKitチームのエンジニア Andrewです これからUIKitアプリを2Dから 3次元の世界に移行させます Graceのアップデートのおかげで サンプルアプリは良い感じになりました 既存のUIKitアプリと同様に 新しい空間APIを使って さらに進化させましょう 今回は 既存のアプリをアップデートして 素晴らしい空間体験を生み出す 簡単な3つの方法を紹介します 始めに UIKit Presentationsには ビューコントローラーのトランジションに 深みを加える空間スタイルがあります 2つ目は コンテンツを 今まで不可能だった シーンの外側に持って行くことを 可能にする新しいAPI Ornamentsです 最後に RealityKitコンテンツを アプリに直接追加する 新しい強力な方法を紹介します それぞれが どのようにして アプリを次のレベルに 引き上げるのかについて説明します おなじみのUIKitプレゼンテーションが 空間コンピューティングで 使用可能になりました サンプルアプリはiPadでシートや アラート ポップオーバーを使っています 新プラットフォームでの 動作について説明します まず アプリの設定を開きます 空間シートがビューコントローラーを 背面に移動させ 輝度を下げます iPadとは異なり ビューコントローラーの isModalInPresentation プロパティに関係なく 枠外へのタッチやその他の ジェスチャーでは解除されません 次に 新しいアラートスタイルを 見てみましょう アプリのアイコンの2D表現が 上部に配置されています シートと同じように 常にビューコントローラーは 背面に移動させられ アラートが表示されます 最後に ドキュメント詳細の ポップオーバーを開きます 少し位置が変ですね 境界の外側に出ているのは素晴らしいですが アプリの中心から遠すぎます コードを見て修正しましょう ビューコントローラーが作成され ポップオーバースタイルに 設定されています… 問題が分かりました permittedArrowDirectionsが 右側だけに設定されています iPadでは ポップオーバーは シーンの制約を受けますが 空間プラットフォームでは macOSと同様に この制約は存在しません これをアップデートして 常にシステムにあった配置にしましょう
これで ボタンをタップすると 期待通りの位置に ポップオーバーが出現しました もしiPadアプリで標準的な プレゼンテーションを使っているなら お使いの空間アプリは すでにベストな位置に表示されているでしょう UIKitは プラットフォームの設定を 直接指定していない限り すべての詳細を処理してくれます 次に オーナメントを使って サンプルアプリを改良しましょう アプリのプレゼンテーションは 空間に対応しましたが エディタ自体は このプラットフォーム特有の 追加のスペースを活用できていません エディタは… …少し狭い場所にあります ですが オーナメントを使えば 空間プラットフォームが提供する 追加のスペースを これまで不可能だった方法で活用できます オーナメントによって アプリのシーン周辺の 適切な 範囲内にコンテンツを配置できます UIKitコンポーネントも ポップオーバーなどで オーナメントを使っています そのため サンプルアプリの ポップオーバーは 見切れることなく シーンの外に表示されました デバイスの多くの内蔵アプリも オーナメントを使っています こちらはヘッドセットで TVを見ている様子です アプリはSwiftUIのタブビューを使い タブバーをシーンの左端に オーナメントとして配置しています Safariはオーナメントを使い ナビゲーションバーを ウェブページの上に表示しています また フリーボードでは 下部の ツールバーにオーナメントを使用しています オーナメントを使えば アプリが主要コンテンツを 中央に配置し コントロールを端へ移動してくれます また オーナメントは浮かび上がり 奥行きが加わっています あらゆる意味で 境界を打ち破っています サンプルアプリでは すべての編集コントロールを ツールバーオーナメントにすると 完璧だと思います Xcodeで追加してみましょう オーナメントはSwiftUIコンテンツを ホストするので SwiftUIのインポートが必要です このファイルではすでに行っています 次に 新規オーナメントを定義します Alignmentパラメータを使えば 皆さんのニーズに最も合った コンテンツのレイアウトを 簡単に表現できます 例えば オーナメントを シーンの左辺 外側に表示させたい場合 先頭寄せと 末尾寄せを設定します 代わりにオーナメントを シーンの内側に表示するには 先頭寄せを使用します 編集ツールバーについては シーン下辺 外側に表示したいが ツールを中央に配置し エディタとの一体感を出したいです その場合は 下部寄せと センタリングを使います 配置設定を追加しましょう コンテンツについては 先にEditingControlsViewを作ったので それを使うことにします 背景はオーナメントに自動で追加されません コンテンツに最適な 正しい背景を選ぶ必要があるからです ツールバーの背景をエディタと 同じガラスにしたいので 新しい修飾子を使います 次に UIViewControllerの新しい Ornamentプロパティに 新しいオーナメント専用の配列を設定します 複数のオーナメントがある場合 それもこの配列に入れておきます オーナメントはビューコントローラーの ライフサイクルを共有します ビューコントローラーが 階層から削除されると そのオーナメントも削除されます この関連付けはシステムの インタラクションにとって重要です 例えば シートプレゼンテーションでは トランジションの間 ビューコントローラーとの 相対的な位置を維持します 最後に 意図しないオーバーラップが 発生しないよう注意しましょう 最後にもう一度 コードを変更します コントロールをオーナメントに移動したので メインエディタのスペースが広くなりました カスタムのedgeToEdgeを使って もう少し大きくしてみましょう アプリを起動します
完璧です! ツールバーが狙いの通り エディタ下部の外側にあります 素晴らしい オーナメントを活用することで アプリのメインエリアをクリエイターが 最も大切に思う コンテンツのために使用でき なおかつ 編集ツールを近くに配置できます オーナメントの作成は簡単です 時間と労力を集中させ アプリをユニークなものにできます 最後に UIKitアプリにRealityKitを 追加する方法を解説します 新しいSwiftUI ViewのRealityViewは RealityKitコンテンツをホストできます これにより エンティティを SwiftUI階層に追加できます RealityViewの 詳細については “Build spatial experiences with RealityKit”をご覧ください また 既存のAPIである UIHostingControllerは SwiftUIビューをホストできます これでUIKitアプリを書き直すことなく SwiftUIの他の新しいAPIと同様に RealityViewを利用することが可能です サンプルアプリでは RealityKitを使って ピクセルに命を吹き込みたいので Xcodeで魔法をかけましょう すでにPixelArtEntityViewという 新しいSwiftUIビューを作成しました RealityViewを使って アートのピクセルを RealityKitのエンティティとして レンダリングします まず新しいインスタンスを作ります 次に UIHostingControllerを設定して エンティティビューを ルートビューとして使います EditorViewControllerの子として ホスティングコントローラーを追加し EditorViewControllerのサブビューとして ホスティングコントローラーの ビューを追加します 次に ホスティングコントローラーが 新しい親に移動したことを伝えます 最後に カスタムレイアウト関数を呼び出し プレビューを配置します ホスティングコントローラーの 設定は完了しました では見てみましょう
再生ボタンを押し 3Dプレビューを タップして 新しいコードの動作を確認します このように アプリにピクセルが追加され 奥行きが生まれました シミュレータの軌道制御を使えば 視点の移動に伴い ライティングも変化しています すごいですね! すべてUIKitアプリ内で出来ています RealityViewはアニメーター プレビューをレベルアップしました UIHostingControllerのおかげで 簡単に追加できました これらのAPIを組み合わせることで 優れた空間アプリ開発の ステップが簡略化されました 標準的なUIKitプレゼンテーションを使い エディターコントロールをオーナメントに入れ RealityKitで3Dピクセルを追加することで サンプルアプリはこの新しい 空間世界で見違えるようになりました しかも加えたコードはわずか数行です こうした空間体験の デザインの指針については “Principles of spatial design”を ご覧ください この動画では多くの内容をカバーしました 次のステップに進みましょう まず プロジェクトの 新しい実行先を追加します デバイス固有のAPIの使い方を変更し 非推奨のAPIの使用を控えましょう セマンティックスタイル ホバーエフェクト 標準的なPresentationsを使用して アプリとプラットフォームの外観に 統一感を持たせましょう またオーナメントを使って アイデアと 創造力を枠の外に広げましょう 空間的なSwiftUI機能を UIKitから直接使うことで アプリをさらに進化させましょう ありがとうございました 皆さんのアプリが 全く新しいプラットフォームに対応するのを Graceと共に 楽しみにしています ♪
-
-
16:15 - permittedArrowDirections
import UIKit extension EditorViewController { @objc func showDocumentPopover(sender: UIBarButtonItem) { let controller = DocumentInfoViewController(document: pixelDocument) controller.modalPresentationStyle = .popover if let presentationController = controller.popoverPresentationController { presentationController.barButtonItem = sender if traitCollection.userInterfaceIdiom == .reality { presentationController.permittedArrowDirections = .any } else { presentationController.permittedArrowDirections = .right } } present(controller, animated: true, completion: nil) } }
-
19:46 - Ornament
extension EditorViewController { func showEditingControlsOrnament() { let ornament = UIHostingOrnament(sceneAlignment: .bottom, contentAlignment: .center) { EditingControlsView(model: controlsViewModel) .glassBackgroundEffect() } self.ornaments = [ornament] editorView.style = .edgeToEdge } }
-
22:45 - UIHostingController
extension EditorViewController { func showEntityPreview() { let entityView = PixelArtEntityView(model: entityViewModel) let controller = UIHostingController(rootView: entityView) addChild(controller) view.addSubview(controller.view) controller.didMove(toParent: self) prepareEditorInteractions() } }
-
22:46 - Using Semantic Colors
private let titleLabelTextField: UITextField = { textField.textColor = UIColor.label return textField }() private let authorLabel: UILabel = { label.textColor = UIColor.secondaryLabel return label }()
-
22:47 - Adding a recessed appearance to a text field
textField.borderStyle = .roundedRect
-
22:48 - Overriding preferredContainerBackgroundStyle
class MyViewController: UIViewController { override var preferredContainerBackgroundStyle: UIContainerBackgroundStyle { return .glass } }
-
22:49 - Customizing hover style
class CollectionViewCell: UICollectionViewCell { init(document: PixelArtDocument) { self.hoverStyle = .init( effect: .highlight, shape: .roundedRect(cornerRadius: 8.0)) } }
-
22:50 - Checking user interface idiom
func fourFingerSwipe() { let gesture = UISwipeGestureRecognizer( target: self, action: #selector(self.deleteAll)) gesture.direction = .left if traitCollection.userInterfaceIdiom == .reality { gesture.numberOfTouchesRequired = 2 } else { gesture.numberOfTouchesRequired = 4 } self.view.addGestureRecognizer(gesture) }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。