View in English

  • Apple Developer
    • Get Started

    Explore Get Started

    • Overview
    • Learn
    • Apple Developer Program

    Stay Updated

    • Latest News
    • Hello Developer
    • Platforms

    Explore Platforms

    • Apple Platforms
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    Featured

    • Design
    • Distribution
    • Games
    • Accessories
    • Web
    • Home
    • CarPlay
    • Technologies

    Explore Technologies

    • Overview
    • Xcode
    • Swift
    • SwiftUI

    Featured

    • Accessibility
    • App Intents
    • Apple Intelligence
    • Games
    • Machine Learning & AI
    • Security
    • Xcode Cloud
    • Community

    Explore Community

    • Overview
    • Meet with Apple events
    • Community-driven events
    • Developer Forums
    • Open Source

    Featured

    • WWDC
    • Swift Student Challenge
    • Developer Stories
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Centers
    • Documentation

    Explore Documentation

    • Documentation Library
    • Technology Overviews
    • Sample Code
    • Human Interface Guidelines
    • Videos

    Release Notes

    • Featured Updates
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • Downloads

    Explore Downloads

    • All Downloads
    • Operating Systems
    • Applications
    • Design Resources

    Featured

    • Xcode
    • TestFlight
    • Fonts
    • SF Symbols
    • Icon Composer
    • Support

    Explore Support

    • Overview
    • Help Guides
    • Developer Forums
    • Feedback Assistant
    • Contact Us

    Featured

    • Account Help
    • App Review Guidelines
    • App Store Connect Help
    • Upcoming Requirements
    • Agreements and Guidelines
    • System Status
  • Quick Links

    • Events
    • News
    • Forums
    • Sample Code
    • Videos
 

Videos

Abrir menú Cerrar menú
  • Colecciones
  • Todos los videos
  • Información

Más videos

  • Información
  • Resumen
  • Código
  • Tutorial de programación: Agrega persistencia con SwiftData

    Descubre cómo funciona SwiftData mientras agregamos persistencia a una app ya existente. Te mostraremos cómo definir tus modelos de datos e integrar datos persistentes a la perfección con SwiftUI. También aprenderás las habilidades básicas para administrar el estado de tu app usando esta API expresiva y declarativa.

    Capítulos

    • 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

    Recursos

    • Wishlist: Planning travel in a SwiftUI app
    • SwiftData
      • Video HD
      • Video SD

    Videos relacionados

    WWDC26

    • Novedades de SwiftData

    WWDC25

    • SwiftData: Analiza a detalle la herencia y migración de esquemas
  • Buscar este video…
    • 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

  • Videos
  • WWDC26
  • Tutorial de programación: Agrega persistencia con SwiftData
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • Apple Intelligence
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Downloads
    • Sample Code
    • Videos
    Open Menu Close Menu
    • Help Guides & Articles
    • Contact Us
    • Forums
    • Feedback & Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • 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 Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Read the latest news.
    Get the Apple Developer app.
    Copyright © 2026 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines