View in English

  • メニューを開く メニューを閉じる
  • Apple Developer
検索
検索を終了
  • Apple Developer
  • ニュース
  • 見つける
  • デザイン
  • 開発
  • 配信
  • サポート
  • アカウント
次の内容に検索結果を絞り込む

クイックリンク

5 クイックリンク

ビデオ

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

その他のビデオ

ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。

  • 概要
  • トランスクリプト
  • コード
  • SwiftUIにおけるAppの重要事項

    新しいAppプロトコルのおかげで、SwiftUIでApp全体を構築できるようになりました。App、SceneおよびViewがいかに相互につながり合うかをご確認ください。短時間で、複雑な作業を経ることなく、最高クラスの製品に期待される機能を容易に実装する方法を学びましょう。 新しいコマンドモディファイアを用いて、インターフェースに機能を簡単に追加する方法や、新しいWindowGroup APIの詳細をご紹介します。このセッションを有効活用するには、ある程度のSwiftUI経験が求められます。未経験の方は、 "Introduction to SwiftUI"をご覧ください。SwiftUIをさらに追求する場合は、 "What's new in SwiftUI"、 "Data essentials in Swift UI"、 "Stacks, grids, and outlines in SwiftUI"、 "Build document-based apps in SwiftUI"も合わせてご覧ください。

    リソース

    • App
    • Scene
    • WindowGroup
      • HDビデオ
      • SDビデオ

    関連ビデオ

    WWDC20

    • Swift UIにおけるデータの重要事項
    • Swiftの型推論を利用する
    • SwiftUI の Stack, Grid, Outline
    • SwiftUI previews向けにAppを構成する
    • SwiftUIでドキュメントベースのAppを構築する
    • SwiftUIのご紹介
    • SwiftUIの新機能
  • ダウンロード

    こんにちは WWDCへようこそ “SwiftUIにおける Appの重要事項” SwiftUIチームのマット・リケットソンです 後で同僚のジェフも紹介します 去年 SwiftUIを紹介しました パワフルな新手法で 偉大なユーザーインターフェイスを構築 Appleの全プラットフォームで使います ビューでユーザーインターフェイスを作り SwiftUI はビューを変更するため API一式を提供 そしてその2つを合わせます

    今年はフレームワークを拡張しました シーンとAppを 発表するための新しいAPIで SwiftUIを使って作れるものを 更に拡大しました つまり今では App全部を SwiftUIさえあれば構築できます このセッションでは 新しいAPIを紹介し ビュー シーン そしてAppが どのように機能するか説明します 次にSwiftUIの シーンアーキテクチャについて説明し ご自身のAppでの カスタマイズ方法をお見せします 最後に 簡単な概略で Appをカスタマイズできる その他のAPIの 詳細の入手場所を説明します それでは まずはビューから始めましょう SwiftUIを使用されたことがある場合は ご存じの通り ビューは重要です なぜならそれぞれのビューが UIの一部を定義するからです Appを見ている時 目に見える全てがビューです 各画像や文字の並びはビューです それを収納するコンテナもまたビューです スクリーン上に見える全てのピクセルが ビューに何らかの形で定義されています

    ただし全ビューが同じ Appのものではありません Appはスクリーン全体を完全に コントロールしてはいないからです その代わり プラットフォームが Appの表示をコントロールします 異なるregionで Appの一部を表示します

    SwiftUIでは これらの異なる regionを“シーン”と呼びます

    シーンの内容をスクリーンに表示する 最も一般的な方法はウインドウです iPadOSなどのプラットフォームは 複数のウインドウを並べて表示できます iOS watchOS そしてtvOS等の プラットフォームは 各Appを1つのフルスクリーン ウインドウで表示することを好みます macOSがいい例です シーンコンテンツが様々な方法で表示されます この場合 関連ウインドウの コレクションが見えます 各ウインドウが異なるシーンコンテンツの デモンストレーションになります

    macOSでも関連ウインドウを 集めることができます 1つのタブ付きウインドウになります その場合 シーンが代わりに 個別タブを表します

    それ自身のシーンも この共有ウインドウを表します 各タブに関連する子シーンの コンテナとして機能します

    これらのシーンの塊が Appのコンテンツを作ります App シーン ビューを合わせて 所有権の統一された階層を作ります

    先ほど言いましたように ビューは基本的な構成要素で スクリーンに見えるものすべてを レンダリングします またはより複雑な ユーザーインターフェイスにもなります

    ビューはシーンコンテンツを作成します そしてプラットフォームでシーンを 個別に表示することもできます

    ビューと同じように これらのシーンを合わせると より複雑なシーンが作れます さっき見たタブ付きウインドウの 例がそうです

    最後に これらのシーンは Appのコンテンツを作成します

    App シーンおよびビューが どのように機能するか分かったので それがSwiftUIコードに どう影響するかを見てみましょう

    これは私がSwiftUIに 書いたAppです Book Clubの本をどれだけ 読んだかが分かります ご覧の通り SwiftUIのAppには 簡潔な宣言が見られます つまり このような ベーシックなAppは ほんの一握りのコード列にしか 当てはまりません 余分なボイラープレートがなければ App固有のコードに 直ちにフォーカスできます

    この場合 実際のApp インターフェイスの定義に ReadingListViewerと呼ばれる ビューを使います

    ReadingListViewerは 私が作ったカスタムビューで これによってリーディングリストを ブラウズできます

    弊社のReadingListViewerは WindowGroupというシーンを内蔵しています

    WindowGroupシーンが管理するウインドウは ReadingListViewがレンダリングする ウインドウです 追加ウインドウを作成したり 同じウインドウ内に新しいタブを作ったり これらの機能をサポートする プラットフォームで行います この後ジェフがWindowGroupについて 詳細を説明します

    WindowGroupシーンは App内に含まれ Appプロトコルに 準拠したカスタムstructで表されます

    コードの構造が 先ほど見た所有者の階層にマッチすることに 気が付くでしょう Appにはシーンが含まれ シーンにはビューが含まれています

    またApp宣言に関しては カスタムビュー宣言に似ていることにも 気が付くでしょう 例えば ビューとAppは両方共 データの依存関係を宣言できます ReadingListViewerがここで ReadingListStoreオブジェクトを監視します

    このAppはReadingListStore オブジェクトにも依存しますが それ自身オブジェクトの所有者で あることも宣言します StateObjectプロパティラッパーを利用します SwiftUIの今年の新機能です

    ビューとAppはまた両方共 “ボディ”プロパティを宣言し ユーザーインターフェイス コンテンツを定義します

    ビューがその他のビューを含むことに ついては先ほどお話しました つまり そのためにビューのボディが ビューを返すのです ところがAppは シーンを使って作成されます そのためボディプロパティは 代わりにシーンを返します

    最後にAppをデコレートしている @main属性に気付かれたと思います これはSwift 5.3の新属性です あるタイプをエントリーポイントとして プログラムを実行します

    通常 Swiftプログラムの実行には main.swiftファイルが必要です @main属性で その責任をアブストラクトに 委任することができます アブストラクトは起動に必要な 全設定を自動的に行い スクリーンに Appを表示します

    コードのレビューをしたところで 少し前の話に戻ります

    ここに見えているのはSwiftUIの ベーシックApp向けの完全な宣言です ほんの一握りのコード列にだけ 当てはまります でも騙されてはいけません 実際には自動でインテリジェントな 動作がたくさんあり このシンプルな宣言に詰め込まれています このAppの仕組みを 本当に理解するには WindowGroupシーンについて もっと語る必要があります それが私たちの ユーザーインターフェイスを管理します そのため ここからジェフに交代します ありがとう マット こんにちは

    まずお見せしたいのは マットが概要をお見せしたコンセプトの デモンストレーションです それからWindowGroupの細かい点について いくつか話します

    私はかなり熱心な読者なので あるAppに取り組んできました 現在読んでいる全ての本の 進捗を記録するためです ご覧の通り 私のAppはiPadOSの 初期ウインドウで起動します コンテンツとして特定したビューを 使用しています 見る限りかなりの本が読みかけのようですね 進捗を確認するために新しいウインドウを 開けてみましょう App Exposeを開けると 新規をここに簡単に作成できます そして違う本にナビゲートします WindowGroupはこの機能を 私のiPadOS上のAppに 自動的に提供します ウインドウそれぞれが インターフェイスのそれぞれの状態に 反映していることが分かります 選択された本はそれぞれで異なり 1つの変更はその他の本に影響しません これはSwiftUIシーンの重要な側面です Appは各モデルに それぞれのシーンを提供しますが 各シーンのビューの状態は独立しています また App Switcherについて いくつかお話しします 各ウインドウは私のAppの 名前を表示しています 選択された本のタイトルも見えます これは今年発売の ビューモディファイアによって行われます “navigation title”といって iOSではナビゲーションバーに タイトルを表示するのに使われ App Switcherでも使われます ビューモディファイアの例です これは親シーンの状態に影響を与えます

    MacではAppが複数のウインドウを サポートするのは一般的です WindowGroupをAppで使うことで SwiftUIはファイルメニューに メニューアイテムを提供し 新しいシーン例の作成をサポートします

    このアイテムは呼びだすこともできます スタンダードCommand-N キーボードショートカットを経由します

    macOSでナビゲーションタイトルが どのように適用されるかが分かります 本のタイトルが表示されます ウインドウのタイトルバーの辺りです

    ウインドウメニューでも使用されます

    良いタイトルを作ることは重要です ユーザーに多くのコンテクストを与え ウインドウを選択する助けにもなります オープンウインドウのリストから選択します 複数のウインドウをサポートするのに加え macOSはウインドウの グループ化もサポートします ウインドウメニューを経由します オープンウインドウを1つのタブ付き インターフェイスにマージできます

    それぞれのタブは個別シーンを表しています

    この機能ではコードを書く必要がありません SwiftUIが自動的に行います

    実演をいくつかお見せしました AppのWindowGroupシーンを 使用しています ここでもう少し詳細を見てみましょう 今お見せしたことを要約すると WindowGroupはシーンです Appの主要インターフェイスを 表現できます

    提供したビューは インターフェイスの定義として使われます

    これは私たちの全プラットフォームで 期待した通りに機能します 例えば iOSとwatchOSでは あなたのビューが表示されるのは デバイスのスクリーン全体を閉める ウインドウです macOSでは このウインドウはビューの定義によって サイズが決まります シーンのライフサイクルは 実行中のプラットフォームにより 管理されます

    macOSを例としましょう プラットフォームがAppに ウインドウを作る必要がある場合 WindowGroupは新しい子シーンを インスタンス化します デフォルトでウインドウ内に コンテンツを表示します

    複数のウインドウをサポートする プラットフォームでは 例えばmacOSやiPadOSですが WindowGroupは複数の子シーンを インスタンス化します

    これはユーザーアクションに 対応する形で起こります 例えば メニューアイテムをクリックしたり マルチタスクジェスチャーを呼び出すことなど

    各シーンはそのユーザーインターフェイスの 定義を共有する一方で この定義を作るビューは すべてそれぞれ独立した状態を持っています

    つまり1つのウインドウで ビュー状態を変えても その他の状態に 影響を与えることはありません

    この機能により テンプレートの提供が可能です インターフェイスに使用できます 一方でユーザーがこのインターフェイスを カスタマイズすることもできます 提供された状態を通して行います

    プラットフォームはシーンの ライフサイクルを担当するため 私たちは今年 新しいプロパティラッパーを紹介しました ビュー状態の修復管理をサポートします SceneStorageプロパティラッパーを使うと ビュー状態を維持できます

    保存状態識別のための 一意のキーが必要です この状態はその後自動的に 保存および修復されます SwiftUIが適宜行います

    ここまでシーンについてお見せしました 特にWindowGroupの仕組みについてです ここでマットにバトンタッチします マットはAppのカスタマイズ方法について 更に詳しく説明します ありがとう ジェフ 最後にお見せしたいのは 今年 利用可能となる その他のApp関連の新機能です

    先ほど見たBook Clubは データ駆動型Appでした 共有のデータモデルに支えられています その他の種類のAppもあります 例えばドキュメントベース Appです このShapeEdit Appがその例です

    今年新しいのは DocumentGroupシーンタイプで 自動的に管理してオープン 編集 そしてドキュメントベースシーンを保存する点 詳細は今年の “Build Document-Based Apps in SwiftUI”を 視聴してください

    それではBook Clubの例に戻りましょう macOS Appの共通項は プリファレンスウインドウです

    今年私たちは新しい“設定”シーンタイプを 発表します macOSで使用でき スタンダードプリファレンスウインドウに 自動的に設定します 設定シーンはプリファレンスコマンドを Appメニューに 自動的に設定します また ウインドウに 正しいスタイルの処理を施します

    メニューコマンドと言えば SwiftUIもAPIを提供します そのためカスタムコマンドを シーンに追加できます それには新コマンドモディファイアを 使用します BookCommandsは 私が定義したカスタムタイプです さっと見てみましょう

    コマンドAPIはパワフルで柔軟です 同じ宣言を使用した 状態駆動プログラムモデルで ビュー シーン Appで使用します コマンドをカスタムタイプに カプセル化できます ユーザーフォーカスに基づく ターゲットアクションで AppKitまたはUIKitの レスポンダーチェーンに似ています 通常のビューを利用して コマンド自身を構築します 参照ドキュメントをご確認ください 詳細やコマンドの使用方法が 説明されています 今年SwiftUIで利用可能な 新しいApp関連APIを ほんの一部ご紹介しました その他のSwiftUIトークの ご視聴もお勧めします ご自身のAppの コンテンツ構築に役立ちます “Data Essentials in SwiftUI”で 知識を深めることができます App シーン およびビューの間での 適切なデータ通信が学べます “What's New in Swift”でお見せするのは 言語における最新の改良について あなたのSwiftUIコードを改良します

    皆さんが すばらしいSwiftUIを 構築されるのを楽しみにしています 作品をフォーラムでシェアしてください フィードバックも次のビルドも お待ちしています 引き続き WWDCをお楽しみください

    • 3:57 - Book club app

      @main
      struct BookClubApp: App {
          @StateObject private var store = ReadingListStore()
      
          var body: some Scene {
              WindowGroup {
                  ReadingListViewer(store: store)
              }
          }
      }
      
      struct ReadingListViewer: View {
          @ObservedObject var store: ReadingListStore
      
          var body: some View {
              NavigationView {
                  List(store.books) { book in
                      Text(book.title)
                  }
                  .navigationTitle("Currently Reading")
              }
          }
      }
      
      class ReadingListStore: ObservableObject {
          init() {}
      
          var books = [
              Book(title: "Book #1", author: "Author #1"),
              Book(title: "Book #2", author: "Author #2"),
              Book(title: "Book #3", author: "Author #3")
          ]
      }
      
      struct Book: Identifiable {
          let id = UUID()
          let title: String
          let author: String
      }
    • 10:21 - Window groups

      @main
      struct BookClubApp: App {
          @StateObject private var store = ReadingListStore()
      
          var body: some Scene {
              WindowGroup {
                  ReadingListViewer(store: store)
              }
          }
      }
      
      struct ReadingListViewer: View {
          @ObservedObject var store: ReadingListStore
      
          var body: some View {
              NavigationView {
                  List(store.books) { book in
                      Text(book.title)
                  }
                  .navigationTitle("Currently Reading")
              }
          }
      }
      
      class ReadingListStore: ObservableObject {
          init() {}
      
          var books = [
              Book(title: "Book #1", author: "Author #1"),
              Book(title: "Book #2", author: "Author #2"),
              Book(title: "Book #3", author: "Author #3")
          ]
      }
      
      struct Book: Identifiable {
          let id = UUID()
          let title: String
          let author: String
      }
    • 12:07 - Scene storage

      @main
      struct BookClubApp: App {
          @StateObject private var store = ReadingListStore()
      
          var body: some Scene {
              WindowGroup {
                  ReadingListViewer(store: store)
              }
          }
      }
      
      struct ReadingListViewer: View {
          @ObservedObject var store: ReadingListStore
          @SceneStorage("selectedItem") private var selectedItem: String?
          
          var selectedID: Binding<UUID?> {
              Binding<UUID?>(
                  get: { selectedItem.flatMap { UUID(uuidString: $0) } },
                  set: { selectedItem = $0?.uuidString }
              )
          }
      
          var body: some View {
              NavigationView {
                  List(store.books) { book in
                      NavigationLink(
                          destination: Text(book.title),
                          tag: book.id,
                          selection: selectedID
                      ) {
                          Text(book.title)
                      }
                  }
                  .navigationTitle("Currently Reading")
              }
          }
      }
      
      class ReadingListStore: ObservableObject {
          init() {}
      
          var books = [
              Book(title: "Book #1", author: "Author #1"),
              Book(title: "Book #2", author: "Author #2"),
              Book(title: "Book #3", author: "Author #3")
          ]
      }
      
      struct Book: Identifiable {
          let id = UUID()
          let title: String
          let author: String
      }
    • 12:59 - Document groups

      import SwiftUI
      import UniformTypeIdentifiers
      
      @main
      struct ShapeEditApp: App {
          var body: some Scene {
              DocumentGroup(newDocument: ShapeDocument()) { file in
                  DocumentView(document: file.$document)
              }
          }
      }
      
      struct DocumentView: View {
          @Binding var document: ShapeDocument
          
          var body: some View {
              Text(document.title)
                  .frame(width: 300, height: 200)
          }
      }
      
      struct ShapeDocument: Codable {
          var title: String = "Untitled"
      }
      
      extension UTType {
          static let shapeEditDocument =
              UTType(exportedAs: "com.example.ShapeEdit.shapes")
      }
      
      extension ShapeDocument: FileDocument {
          static var readableContentTypes: [UTType] { [.shapeEditDocument] }
          
          init(fileWrapper: FileWrapper, contentType: UTType) throws {
              let data = fileWrapper.regularFileContents!
              self = try JSONDecoder().decode(Self.self, from: data)
          }
      
          func write(to fileWrapper: inout FileWrapper, contentType: UTType) throws {
              let data = try JSONEncoder().encode(self)
              fileWrapper = FileWrapper(regularFileWithContents: data)
          }
      }
    • 13:27 - Settings scene

      @main
      struct BookClubApp: App {
          @StateObject private var store = ReadingListStore()
      
          @SceneBuilder var body: some Scene {
              WindowGroup {
                  ReadingListViewer(store: store)
              }
              
          #if os(macOS)
              Settings {
                  BookClubSettingsView()
              }
          #endif
          }
      }
      
      struct BookClubSettingsView: View {
          var body: some View {
              Text("Add your settings UI here.")
                  .padding()
          }
      }
      
      struct ReadingListViewer: View {
          @ObservedObject var store: ReadingListStore
      
          var body: some View {
              NavigationView {
                  List(store.books) { book in
                      Text(book.title)
                  }
                  .navigationTitle("Currently Reading")
              }
          }
      }
      
      class ReadingListStore: ObservableObject {
          init() {}
      
          var books = [
              Book2(title: "Book #1", author: "Author #1"),
              Book2(title: "Book #2", author: "Author #2"),
              Book2(title: "Book #3", author: "Author #3")
          ]
      }
      
      struct Book: Identifiable {
          let id = UUID()
          let title: String
          let author: String
      }
    • 14:07 - BookCommands

      struct BookCommands: Commands {
          @FocusedBinding(\.selectedBook) private var selectedBook: Book?
          
          var body: some Commands {
              CommandMenu("Book") {
                  Section {
                      Button("Update Progress...", action: updateProgress)
                          .keyboardShortcut("u")
                      Button("Mark Completed", action: markCompleted)
                          .keyboardShortcut("C")
                  }
                  .disabled(selectedBook == nil)
              }
          }
          
          private func updateProgress() {
              selectedBook?.updateProgress()
          }
          private func markCompleted() {
              selectedBook?.markCompleted()
          }
      }
  • 特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。

    クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。

Developer Footer

  • ビデオ
  • WWDC20
  • SwiftUIにおけるAppの重要事項
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習
    • オープンソース(英語)
    • セキュリティ
    • 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(英語)
    • 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 © 2025 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン