ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
SwiftDataでアプリを構築
SwiftDataがアプリでデータを持続するのにどのように役立つかを見ていきます。マルチプラットフォームのSwiftUIアプリをSwiftDataとともに一緒に開発していきます。既存のモデルクラスをSwiftDataモデルに変換し、環境をセットアップし、モデルレイヤーの変更をUIに反映し、SwiftDataストレージに支えられたドキュメントベースのアプリケーションを構築する方法を学びます。このセッションを最大限に活用するためには、SwiftDataに精通している必要があります。紹介についてはWWDC23の「Meet SwiftData」をご覧ください。
関連する章
- 0:00 - Meet the app
- 3:09 - SwiftData models
- 5:30 - Querying models to display in UI
- 9:43 - Creating and updating
- 12:30 - Document-based apps
リソース
関連ビデオ
WWDC23
-
ダウンロード
こんにちは! 私はJuliaです SwiftUIのエンジニアです 最近 Swiftでモデルレイヤーを 持続する新しい方法である SwiftDataを導入しました 今日のセッションでは SwiftUIアプリで SwiftDataを円滑に 統合する方法を見ていきましょう SwiftDataモデルとのスムーズな統合を 可能にするSwiftUIの 新しい機能について説明します 基本的なことをカバーするために 「Meet SwiftData」のセッションを まだ視聴していない場合は まずそちらを見てください SwiftDataとSwiftUIがどのように 連携するかを見るために フラッシュカードのアプリを作りましょう 以前から 偉大な発明の 日付や作者を記憶するのに役立つ ツールを作りたいと思っていました SwiftDataはこのタスクに最適です フラッシュカードデッキを保存して おくのに役立つので 時間があるときにいつでも開いて クリックできます 私はこのアプリをMac iPhone Watch TVなど どこでも動作させたいと思っていますが SwiftDataがサポートしてくれます すべてのプラットフォームで利用可能です これはcode alongです このセッションでは みなさんと一緒にアプリを作ります 今すぐ一時停止を押して セッションのResourceにあるの Xcodeプロジェクトを ダウンロードしてください スタータープロジェクトを開き ContentViewファイルに移動します このセッションでは Xcodeの新機能である インタラクティブなLive Previewsを 活用します Previewsのセクションには フラッシュ カードが何枚か並んだグリッドがあります 任意のカードをクリックすると カードを1枚ずつスクロールできる ビューに遷移します 誰がコンパイラを発明したか 覚えていますか? カードをクリックしてください カードがめくられ 答えが表示されます! アプリにはメモリに保存された サンプルカードが読み込まれており アプリを実行して新しいカードを追加しても アプリを閉じると消えてしまいます そこでSwiftDataの出番です 作成したフラッシュカードを 持続させるために使います 今日は SwiftDataを使い始めるために 知っておく必要がある すべてのことについて 私がまとめた このやることリストの項目を 次々にチェックしながらお話します あなたは今 私たちが作るアプリに 出会ったところです 次に スタータープロジェクトと そのモデルクラスを見てみましょう それから 手順を追って SwiftDataをストレージとして 使用するように変換し 修正します モデルクラスを拡張して SwiftDataモデルにする方法 データを照会してモデルレイヤーの すべての変更でビューを更新する方法 モデルを作成して保存する方法 またUI要素をバインドする方法を学びます そして最後には ボーナスとして SwiftDataがストレージを管理するとき 文書ベースのアプリを作成するのが いかに簡単かを見ていきます スタータープロジェクトでは 時間を節約するために 1枚のフラッシュカードと いくつかのビューおよびサポートファイルを表す Cardモデルを定義しました すべてのカードには 表面と裏面の テキストと作成日が保存されます かなり典型的なモデルです SwiftDataがそれを 保存できるように更新しましょう 最初に SwiftDataを このファイルにインポートします そして次に必要な主な変更は @Modelマクロを定義に追加することです そして今 クラスはSwiftDataで 完全に永続化可能です もうタイプする必要はありません これだけです! さらに @Modelを使うと カードは Observableプロトコルに一致するようになり ObservableObjectの代わりに それを使うようになります ObservableObjectと @Publishedプロパティラッパーへの 一致を削除します 以前 ObservedObject一致を使って CardEditorViewファイルのUIから 直接カードを編集していました ここでObservableを採用するために "ObservedObject"プロパティラッパーを "Bindable"に置き換えます これにより テキストフィールドを カードの表面と裏面のテキストに 直接バインドできます 完了しました! 新しいObservableマクロと Bindableプロパティラッパーにより 以前よりもさらに少ないコードで アプリ内のデータフローを 簡単に設定できるようになりました ViewがそのボディでObservable型の プロパティを使用する場合 指定されたプロパティが変更されると 自動的に更新されます そして モデルの変更可能な状態を UI要素にバインドするのが これほど簡単だったことはありません! WWDC23 セッション 「Discover Observation with SwiftUI」を ぜひご覧ください SwiftDataの有無にかかわらず Observableがデータフローのコードを いかに単純化するか驚くことでしょう モデルについて知る必要があるのは これだけです それ以上何もありません なんて素晴らしいんでしょう 次に SwiftDataからモデルを照会して UIに表示するために ContentViewに切り替えましょう SampleDeck.contentsの代わりに SwiftDataが持っているカードを表示します
そして カードの配列をSwiftData ストレージにバインドするために 必要な変更が1つあります @Stateプロパティのラッパーを @Queryに置き換えることです それだけです! プレビューでわかるように これ以上表示するカードはありません おそらく何も保存していないためです SwiftDataによって管理されるモデルを UIに表示したいときは いつでも@Queryを使います @QueryはSwiftDataからモデルに 問い合わせる新しいプロパティラッパーです また@Stateの場合と同様に モデルが変更されるたびに ビューの更新も作動します すべてのビューは 必要な数のクエリされた プロパティーを持つことができます クエリは 並べ替え 順序付け フィルタリング さらには 変更のアニメーションを設定するための lightweight syntaxを提供します 内部では ビューのmodel contextを データソースとして使用します @Queryにmodel contextを提供するには どうすればいいでしょうか? ModelContainerから1つ取ってきます SwiftUIは ビューのModelContainerを 便利に設定するための 新しいビューとシーンModifierを提供します SwiftDataを使うのに アプリは 最低でも1つのModelContainerを準備します @Queryが使用するcontextを含む ストレージスタック全体を作成します ビューは1つのModelContainerを持ちますが アプリはビュー階層ごとに 必要な数のコンテナを作成し 使用できます アプリがmodelContainerを設定しない場合 ウィンドウと作成するビューは SwiftData経由でモデルを保存したり クエリしたりできません 多くのアプリは単一の ModelContainerを必要とします この場合 ウィンドウグループ全体の シーンに対して設定できます ウィンドウとそのビューはコンテナを継承し 同じグループから作成された 他のウィンドウも継承します これらのビューはすべて単一のコンテナから 書き込みと読み込みを行います アプリによっては いくつかの ストレージスタックを必要とし ウィンドウごとに複数の ModelContainerを設定できます SwiftUIはまた ビューレベルで きめ細かい設定が可能です 同じウィンドウ内の異なるビューは 別々のコンテナを持つことができ 1つのコンテナで保存しても 他のコンテナには影響しません それでは Queryにデータソースを提供する modelContainerを設定しましょう アプリの定義を開いて
そして アプリのウィンドウの ModelContainerを設定します サブビューが作成 読み込み 更新 削除できるのは ビューmodifierにリストされた モデルタイプだけなことに注意してください これで設定は完了です! しかし 追加の手順を1つ実行して プレビューにサンプルデータを提供します アプリの中でサンプルカードを入れた インメモリコンテナを定義しました "PreviewSampleData"ファイルを開き 対象に組み込みましょう このファイルには サンプルデータを含む コンテナの定義が含まれています これをContentViewで使い プレビューを サンプル・カードで満たします [音声なし]
これで@Queryにデータのソースができたので プレビューにカードが表示されます! これがSwiftDataスタックを準備し プレビューを生成するために必要な すべての設定です 次に SwiftDataが私が作成した 新しいカードと既存のカードに 加えられた変更を追跡して 保存することを確認します そのために ビューのmodel contextを使います model contextにアクセスするために SwiftUIは新しい環境変数を提供します ModelContainerと同様に 各ビューは1つのcontextを持ちますが 一般的にアプリは必要な数だけ contextを持つことができます このアプリでは contextは すでに設定されています この環境変数は 先に ModelContainerを設定したときに 自動的に設定されました Xcodeに戻りましょう カードを保存したり更新したりするには modelContextにアクセスする必要があります [音声なし]
[音声なし]
SwiftDataに保存したいモデルを 認識させるために model contextに 新しく作成されたカードを挿入します
モデルを挿入した後 "modelContext.save()"を呼び出して contextを保存する必要があると 思うかもしれませんが その必要はありません SwiftDataの素晴らしい点は model contextを自動保存することです 自動保存は UI関連のイベントや ユーザー入力によって動作します 保存は SwiftDataがやってくれるので 心配する必要はありません 例えば SwiftDataストレージを共有したり 送信したりする前に すべての変更がすぐに持続することを 確認したい場合はほとんどありません このような場合は 明確に"save()"を 呼び出します カードを保存して 照会できるようになったので カードを作ってみましょう! アプリを起動して プラスボタンを押してカードを作ります 前に見たCompilerカードを追加しましょう [音声なし] では アプリを終了してもう一度起動し 新しいカードがあるか確認してみましょう
ここにありました! これで ビューのmodel contextにアクセスして カードを追加する方法がわかりました 完了しました! 新しいウィンドウを開きましょう 最初のデッキと同じデッキが表示されます これは 両方のウィンドウが 同じModelContainerを使い 同じデータに アクセスするため 当然のことです しかし このアプリが別のウィンドウで 別のフラッシュカードデッキを開くことが できれば素晴らしいでしょう 基本的には すべてのデッキを個別の 文書として扱いたいということです そして これらの文書を友人と共有できます 文書ベースのアプリは macOS iOS iPadOSで使われている概念です ユーザーが異なるタイプの文書を作成したり 開いたり 閲覧したり 編集したりを 可能にする 特定のタイプの アプリについて説明します すべての文書はファイルであり ユーザーは それらを保存 コピー 共有できます そして SwiftUIがSwiftDataで バックアップされた文書アプリを サポートしていることを お知らせできて嬉しいです この方法を試してみましょう FlashCardAppファイルを開きます 文書ベースのアプリはiOSとmacOSに存在し このプラットフォームでは DocumentGroupの initializerの使用に切り替えます
[音声なし]
[音声なし]
モデルタイプ Card.self コンテンツタイプ ビュービルダーを渡します 少し回り道をして 2番目のパラメータである コンテンツタイプについて 詳しく説明しましょう! SwiftData文書ベースのアプリは custom content型を宣言する必要があります それぞれのSwiftData文書は 固有のモデルのセットから構築され ディスク上で固有の表現を持っています 文書のcontextでは コンテンツタイプは JPEGのようなバイナリファイル形式と 考えることができます 文書のもう一つのタイプである パッケージは Xcodeプロジェクトのようにディスク上に 固定された構造を持つディレクトリです 例えば すべてのJPEG画像は 同じバイナリ構造を持っています そうでなければ 写真編集者は その読み方を知らないでしょう 同様に すべてのXcodeプロジェクトは 特定のディレクトリとファイルを含みます ユーザーがデッキを開くとき オペレーティングシステムが デッキのフォーマットとファイル拡張子を アプリに関連付ける必要があります そのため コンテンツタイプを 宣言する必要があります SwiftData文書はパッケージです "externalStorage"属性で SwiftDataモデルの いくつかのプロパティをマークすると すべての外部保存項目は 文書パッケージの一部になります UTType+FlashCardsファイルには 新しいコンテンツタイプの定義があるので コードで便利に使うことができます 同じ定義をInfo.plistにも記述します
これから オペレーティングシステムに 新しいコンテンツタイプを宣言します アプリが作成したカードデッキを 他の文書と区別するために ファイルの拡張子を指定する必要があります このサンプルアプリでは "sampledeck"を 拡張子として使用します
フラッシュカードデッキのような 簡単な説明も加えます
識別子はコード内のものと全く 同じでなければいけません
SwiftData文書はパッケージなので タイプがcom.apple.package.SwiftDataに 準拠していることを 確認する必要があります では 宣言したコンテンツタイプを 使ってみましょう アプリの定義に戻り コンテンツタイプを DocumentGroupに渡しています ビュービルダーは同じように見えます
注目すべきは ModelContainerを 設定しないことです 文書インフラは 文書ごとに1つずつ設定します アプリを実行して どのように見えるか見てみましょう! アプリはパネルを開いた状態で起動します 文書ベースのアプリの標準動作で 新しい文書を作成して そこにカードを追加します 文書には 未保存の変更があることを示す ツールバーのサブタイトルが表示されます Command+Sを押すと 保存ダイアログが表示されます デッキは 先ほどInfo.plistに入れたのと 同じ拡張子で保存されることに 注意してください 新しいデッキを保存すると デスクトップに初めてのフラッシュカード デッキができあがりました Command+Nで新しいデッキを作ることも できますし Command+Oでデッキを開くこともできます これらのショートカットは 他の多くの機能と同様に 文書ベースのアプリが 自動的に取得します 要約すると SwiftUIアプリでSwiftData ストレージを使用する方法を学びました 新しい@Modelマクロ @Queryプロパティラッパー model contextのための新しい Environment変数について説明し SwiftDataを文書のストレージとして 使用することが いかに簡単であるかを確認しました 今日はありがとうございました アプリ作りを楽しんでください! ♪ ♪
-
-
3:33 - Defining a SwiftData model
@Model final class Card { var front: String var back: String var creationDate: Date init(front: String, back: String, creationDate: Date = .now) { self.front = front self.back = back self.creationDate = creationDate } }
-
4:25 - Binding to a SwiftData model
@Bindable var card: Card
-
5:52 - Query models from SwiftData storage
@Query private var cards: [Card]
-
8:27 - Setting up a model container for the window group
WindowGroup { ContentView() } .modelContainer(for: Card.self)
-
9:24 - Providing a preview with sample data
#Preview { ContentView() .frame(minWidth: 500, minHeight: 500) .modelContainer(previewContainer) }
-
10:30 - Accessing the model context of the ContentView
@Environment(\.modelContext) private var modelContext
-
10:51 - Insert a new model in the context
let newCard = Card(front: "Sample Front", back: "Sample Back") modelContext.insert(object: newCard)
-
13:34 - Start document-based application setup
@main struct SwiftDataFlashCardSample: App { var body: some Scene { #if os(iOS) || os(macOS) DocumentGroup(editing: Card.self, contentType: <#UTType#>) { <#code#> } #else WindowGroup { ContentView() .modelContainer(for: Card.self) } #endif } }
-
16:51 - Finish document-based application setup
@main struct SwiftDataFlashCardSample: App { var body: some Scene { #if os(iOS) || os(macOS) DocumentGroup(editing: Card.self, contentType: .flashCards) { ContentView() } #else WindowGroup { ContentView() .modelContainer(for: Card.self) } #endif } }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。