View in English

  • Apple Developer
    • 今すぐ始める

    「今すぐ始める」を詳しく見る

    • 概要
    • 学ぶ
    • Apple Developer Program

    最新情報

    • 最新ニュース
    • Hello Developer
    • プラットフォーム

    プラットフォームを詳しく見る

    • Appleプラットフォーム
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    特集

    • デザイン
    • 配信
    • ゲーム
    • アクセサリ
    • Web
    • Home
    • CarPlay
    • テクノロジー

    テクノロジーを詳しく見る

    • 概要
    • Xcode
    • Swift
    • SwiftUI

    特集

    • アクセシビリティ
    • App Intent
    • Apple Intelligence
    • ゲーム
    • 機械学習とAI
    • セキュリティ
    • Xcode Cloud
    • コミュニティ

    コミュニティを詳しく見る

    • 概要
    • 「Appleに相談」イベント
    • コミュニティによるイベント
    • デベロッパフォーラム
    • オープンソース

    特集

    • WWDC
    • Swift Student Challenge
    • デベロッパストーリー
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Center
    • ドキュメント

    ドキュメントを詳しく見る

    • ドキュメントライブラリ
    • テクノロジー概要
    • サンプルコード
    • ヒューマンインターフェイスガイドライン
    • ビデオ

    リリースノート

    • 注目のアップデート
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • ダウンロード

    ダウンロードを詳しく見る

    • すべてのダウンロード
    • オペレーティングシステム
    • アプリ
    • デザインリソース

    特集

    • Xcode
    • TestFlight
    • フォント
    • SF Symbols
    • Icon Composer
    • サポート

    サポートを詳しく見る

    • 概要
    • ヘルプガイド
    • デベロッパフォーラム
    • フィードバックアシスタント
    • お問い合わせ

    特集

    • アカウントヘルプ
    • App Reviewガイドライン
    • App Store Connectヘルプ
    • 近日導入予定の要件
    • 契約およびガイドライン
    • システムステータス
  • クイックリンク

    • イベント
    • ニュース
    • Forum
    • サンプルコード
    • ビデオ
 

ビデオ

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

その他のビデオ

  • 概要
  • Summary
  • コード
  • Code Along:SwiftDataによる永続性の追加

    SwiftData活用の実例を確認しながら、既存のアプリに永続性を追加する方法を学びましょう。データモデルを定義し、永続化したデータをSwiftUIとシームレスに統合する方法をお見せします。また、この表現力に優れた宣言型のAPIを使ってアプリの状態を管理するための基本的なスキルも学びます。

    関連する章

    • 0:00 - Introduction
    • 1:05 - Identify relevant state
    • 3:17 - Define your schemas
    • 9:41 - Define model relationships
    • 13:33 - Update the view layer
    • 21:47 - Next steps

    リソース

    • Wishlist: Planning travel in a SwiftUI app
    • SwiftData
      • HDビデオ
      • SDビデオ

    関連ビデオ

    WWDC26

    • SwiftDataの新機能

    WWDC25

    • SwiftData:継承とスキーマの移行の詳細
  • このビデオを検索
    • 3:39 - Convert Activity to a persistent model with @Model

      import Foundation
      import SwiftData
      
      // SwiftData automatically generates Observable conformance
      @Model
      class Activity {
          var name: String
          var isComplete: Bool = false
          var dateCreated = Date.now
          var dateEdited = Date.now
      }
    • 6:06 - Add Codable conformance to TripCollection

      enum TripCollection: String, CaseIterable, RawRepresentable, Codable {
          case springEscapes
          case summerVibes
          case fallGetaways
          case winterRetreats
      }
    • 10:32 - Set up model relationships between Trip, TripImage, and Activity

      import Foundation
      import SwiftData
      
      @Model
      class Trip {
          var name: String
          var collection: TripCollection
        
          var photo: TripImage
          var thumbnailData: Data?
        
          @Relationship(deleteRule: .cascade, inverse: \Activity.trip)
          var activities: [Activity] = []
        
          private(set) var creationDate = Date.now
          var subtitle: String?
          var isComplete: Bool = false
      }
    • 13:21 - Enable interoperability between your schema and SwiftUI views

      import SwiftUI
      import SwiftData
      
      @main
      struct WishlistApp: App {
          let container: ModelContainer = {
              do {
                  let modelContainer = try ModelContainer(for: Trip.self, Activity.self, TripImage.self, Goal.self, TripGoal.self, ActivityGoal.self)
                  try SampleData.seedIfNeeded(in: modelContainer.mainContext)
                  return modelContainer
              } catch {
                  fatalError("Could not create model container: \(error)")
              }
          }()
      
          var body: some Scene {
              WindowGroup {
                  ContentView()
                      .preferredColorScheme(.dark)
              }
              .modelContainer(container)
          }
      }
    • 16:27 - Fetch achieved and upcoming goals

      @Query(filter: #Predicate<Goal> { $0.isAchieved }, sort: \Goal.dateAchieved, order: .reverse)
      private var achievedGoals: [Goal]
      
      @Query(filter: #Predicate<Goal> { !$0.isAchieved }, sort: \Goal.sortOrder)
      private var upcomingGoals: [Goal]
    • 16:49 - Fetch recent trips

      import SwiftUI
      import SwiftData
      
      struct RecentTripsPageView: View {
          // Fetch most recent trips in reverse chronological order
          @Query(FetchDescriptor<Trip>(sortBy: [SortDescriptor(\Trip.creationDate, order: .reverse)], fetchLimit: 5))
          private var trips: [Trip]
      
          @Namespace private var namespace
      
          var body: some View {
              TabView {
                  ForEach(trips) { trip in
                      NavigationLink {
                          TripDetailView(trip: trip)
                              .navigationTransition(
                                  .zoom(sourceID: trip.id, in: namespace))
                      } label: {
                          TripImageView(trip: trip)
                              .overlay(alignment: .bottomLeading) {
                                  VStack(alignment: .leading) {
                                      Text("RECENTLY ADDED")
                                          .font(.subheadline)
                                          .fontWeight(.bold)
                                          .foregroundStyle(.limeGreen)
      
                                      Text(trip.name)
                                          .font(.title)
                                          .fontWidth(.expanded)
                                          .fontWeight(.medium)
                                          .foregroundStyle(.primary)
                                  }
                                  .padding(.horizontal)
                                  .padding(.bottom, 54)
                              }
                              .matchedTransitionSource(id: trip.id, in: namespace)
                      }
                      .buttonStyle(.plain)
                  }
              }
              .tabViewStyle(.page)
              .containerRelativeFrame([.horizontal, .vertical]) { length, axis in
                  if axis == .vertical {
                      return length / 1.3
                  } else {
                      return length
                  }
              }
          }
      }
    • 17:26 - Dynamically construct a query in the initializer of TripCollectionView

      init(tripCollection: TripCollection, cardSize: TripCard.Size, namespace: Namespace.ID) {
          _trips = Query(filter: #Predicate<Trip> { $0.collection == tripCollection }, sort: \Trip.name)
          self.tripCollection = tripCollection
          self.cardSize = cardSize
          self.namespace = namespace
      }
    • 18:13 - Search for trips and activities by name

      import SwiftUI
      import SwiftData
      
      private struct SearchResultsListView: View {
          @Query(sort: \Trip.name) private var trips: [Trip]
          @Query(sort: \Activity.name) private var activities: [Activity]
      
          var searchText: String
          var namespace: Namespace.ID
      
          init(searchText: String, namespace: Namespace.ID) {
              self.searchText = searchText
              self.namespace = namespace
      
              if searchText.isEmpty {
                  _trips = Query(FetchDescriptor(sortBy: [SortDescriptor(\Trip.creationDate, order: .reverse)], fetchLimit: 3))
                  _activities = Query(filter: #Predicate<Activity> { _ in false })
              } else {
                  // All trips whose name matches searchText, sorted lexicographically
                  let tripSearchPredicate = #Predicate<Trip> { $0.name.localizedStandardContains(searchText) }
                  _trips = Query(filter: tripSearchPredicate, sort: \Trip.name)
                  // All matching activities that belong to a trip
                  let activitySearchPredicate = #Predicate<Activity> { $0.trip != nil && $0.name.localizedStandardContains(searchText) }
                  _activities = Query(filter: activitySearchPredicate, sort: \Activity.name)
              }
          }
      
          var body: some View {
              List {
                  if !trips.isEmpty {
                      TripSearchSectionView(trips: trips, namespace: namespace, title: searchText.isEmpty ? "Recent Trips" : "Trips")
                  }
      
                  if !activities.isEmpty {
                      ActivitySearchSectionView(activities: activities)
                  }
              }
              .overlay {
                  if trips.isEmpty && activities.isEmpty {
                      ContentUnavailableView(
                          "No results for “\(searchText)”",
                          systemImage: "magnifyingglass",
                          description: Text("Check spelling or try a new search.")
                      )
                  }
              }
              .listStyle(.plain)
          }
      }
    • 19:42 - Capture and report errors from ActivityItemView

      var body: some View {
          HStack(alignment: .firstTextBaseline, spacing: 17) {
              Group {
                  if isEditing {
                      rowContentWhenEditing
                  } else {
                      rowContentWhenNotEditing
                  }
              }
              .transition(.opacity.animation(.snappy))
              .animation(.snappy, value: isEditing)
          }
          .onDisappear {
              do {
                  try updateGoalAchievements()
              } catch {
                  updateError = error
                  reportError(error)
              }
          }
          .alert(error: $updateError) {
              // Customize the presentation of the error
          }
      }
    • 21:04 - Update dateEdited and propagate side effects on property changes

      init(activity: Activity, isLast: Bool, isEditing: Bool) {
          activity.token = withContinuousObservation(options: .didSet) { event in
              _ = activity.name
              _ = activity.isComplete
      
              if event.matches(\Activity.name) {
                  activity.dateEdited = .now
              }
      
              if event.matches(\Activity.isComplete) {
                  activity.dateEdited = .now
                  activity.trip?.isComplete = activity.trip?.activities.isEmpty == false
                  && activity.trip?.activities.allSatisfy { $0.isComplete } == true
              }
          }
          self.activity = activity
          self.isLast = isLast
          self.isEditing = isEditing
      }
    • 0:00 - Introduction
    • An introduction to the Wishlist sample app and the three steps for adopting SwiftData: identifying relevant state, defining schemas, and defining model relationships.

    • 1:05 - Identify relevant state
    • Identify the data types and variables in Wishlist — trip collections, goal statuses, and the DataSource — that will become SwiftData models connected through a ModelContext.

    • 3:17 - Define your schemas
    • Convert Activity, Trip, and Goal into @Model types. Covers handling property observers with the @Model macro, refactoring the Goal enumeration into a class hierarchy using inheritance with TripGoal and ActivityGoal subclasses, and inlining thumbnail data.

    • 9:41 - Define model relationships
    • Declare to-many relationships between Trip and Activity using the @Relationship macro, remove the now-redundant DataSource and TripEditModel helpers, and attach the modelContainer scene modifier to complete the model layer.

    • 13:33 - Update the view layer
    • Replace environment DataSource properties with @Query macros and targeted FetchDescriptor predicates in each subview. Covers autosave, surfacing runtime errors with SwiftUI view modifiers, and re-enabling dateEdited property observers using the new withContinuousObservation API.

    • 21:47 - Next steps
    • Key takeaways: design a schema that fits your data model, balance memory and disk usage with targeted queries, and plan for interoperability and extensibility as your app evolves.

Developer Footer

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