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
 

Vídeos

Abrir menu Fechar menu
  • Coleções
  • Todos os vídeos
  • Sobre

Mais vídeos

  • Sobre
  • Código
  • SwiftUI essentials

    Join us on a tour of SwiftUI, Apple's declarative user interface framework. Learn essential concepts for building apps in SwiftUI, like views, state variables, and layout. Discover the breadth of APIs for building fully featured experiences and crafting unique custom components. Whether you're brand new to SwiftUI or an experienced developer, you'll learn how to take advantage of what SwiftUI has to offer when building great apps.

    Capítulos

    • 0:00 - Introduction
    • 1:34 - Fundamentals of views
    • 13:06 - Bulit-in capability
    • 17:36 - Across all platforms
    • 20:30 - SDK interoperability

    Recursos

    • SwiftUI Pathway
    • Forum: UI Frameworks
    • Learning SwiftUI
    • SwiftUI
      • Vídeo HD
      • Vídeo SD

    Vídeos relacionados

    WWDC24

    • Xcode essentials

    WWDC20

    • Introduction to SwiftUI
  • Buscar neste vídeo...
    • 2:30 - Declarative views

      Text("Whiskers")
      
      Image(systemName: "cat.fill")
      
      Button("Give Treat") {
         // Give Whiskers a treat
      }
    • 2:43 - Declarative views: layout

      HStack {
         Label("Whiskers", systemImage: "cat.fill")
      
         Spacer()
      
         Text("Tightrope walking")
      }
    • 2:56 - Declarative views: list

      struct ContentView: View {
          @State private var pets = Pet.samplePets
      
          var body: some View {
              List(pets) { pet in
                  HStack {
                      Label("Whiskers", systemImage: "cat.fill")
      
                      Spacer()
      
                      Text("Tightrope walking")
                  }
              }
          }
      }
      
      struct Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          let id = UUID()
          var name: String
          var kind: Kind
          var trick: String
      
          init(_ name: String, kind: Kind, trick: String) {
              self.name = name
              self.kind = kind
              self.trick = trick
          }
      
          static let samplePets = [
              Pet("Whiskers", kind: .cat, trick: "Tightrope walking"),
              Pet("Roofus", kind: .dog, trick: "Home runs"),
              Pet("Bubbles", kind: .fish, trick: "100m freestyle"),
              Pet("Mango", kind: .bird, trick: "Basketball dunk"),
              Pet("Ziggy", kind: .lizard, trick: "Parkour"),
              Pet("Sheldon", kind: .turtle, trick: "Kickflip"),
              Pet("Chirpy", kind: .bug, trick: "Canon in D")
          ]
      }
    • 3:07 - Declarative views: list

      struct ContentView: View {
          @State private var pets = Pet.samplePets
      
          var body: some View {
              List(pets) { pet in
                  HStack {
                      Label(pet.name, systemImage: pet.kind.systemImage)
      
                      Spacer()
      
                      Text(pet.trick)
                  }
              }
          }
      }
      
      struct Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          let id = UUID()
          var name: String
          var kind: Kind
          var trick: String
      
          init(_ name: String, kind: Kind, trick: String) {
              self.name = name
              self.kind = kind
              self.trick = trick
          }
      
          static let samplePets = [
              Pet("Whiskers", kind: .cat, trick: "Tightrope walking"),
              Pet("Roofus", kind: .dog, trick: "Home runs"),
              Pet("Bubbles", kind: .fish, trick: "100m freestyle"),
              Pet("Mango", kind: .bird, trick: "Basketball dunk"),
              Pet("Ziggy", kind: .lizard, trick: "Parkour"),
              Pet("Sheldon", kind: .turtle, trick: "Kickflip"),
              Pet("Chirpy", kind: .bug, trick: "Canon in D")
          ]
      }
    • 4:24 - Declarative and imperative programming

      struct ContentView: View {
          @State private var pets = Pet.samplePets
      
          var body: some View {
              Button("Add Pet") {
                  pets.append(Pet("Toby", kind: .dog, trick: "WWDC Presenter"))
              }
      
              List(pets) { pet in
                  HStack {
                      Label(pet.name, systemImage: pet.kind.systemImage)
      
                      Spacer()
      
                      Text(pet.trick)
                  }
              }
          }
      }
      
      struct Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          let id = UUID()
          var name: String
          var kind: Kind
          var trick: String
      
          init(_ name: String, kind: Kind, trick: String) {
              self.name = name
              self.kind = kind
              self.trick = trick
          }
      
          static let samplePets = [
              Pet("Whiskers", kind: .cat, trick: "Tightrope walking"),
              Pet("Roofus", kind: .dog, trick: "Home runs"),
              Pet("Bubbles", kind: .fish, trick: "100m freestyle"),
              Pet("Mango", kind: .bird, trick: "Basketball dunk"),
              Pet("Ziggy", kind: .lizard, trick: "Parkour"),
              Pet("Sheldon", kind: .turtle, trick: "Kickflip"),
              Pet("Chirpy", kind: .bug, trick: "Canon in D")
          ]
      }
    • 5:33 - Layout container

      HStack {
         Label("Whiskers", systemImage: "cat.fill")
      
         Spacer()
      
         Text("Tightrope walking")
      }
    • 5:41 - Container views

      struct ContentView: View {
          var body: some View {
              HStack {
                  Image(whiskers.profileImage)
      
                  VStack(alignment: .leading) {
                      Label("Whiskers", systemImage: "cat.fill")
                      Text("Tightrope walking")
                  }
      
                  Spacer()
              }
          }
      }
      
      let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers")
      
      struct Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          let id = UUID()
          var name: String
          var kind: Kind
          var trick: String
          var profileImage: String
      
          init(_ name: String, kind: Kind, trick: String, profileImage: String) {
              self.name = name
              self.kind = kind
              self.trick = trick
              self.profileImage = profileImage
          }
      }
    • 6:23 - View modifiers

      struct ContentView: View {
          var body: some View {
              Image(whiskers.profileImage)
                  .clipShape(.circle)
                  .shadow(radius: 3)
                  .overlay {
                      Circle().stroke(.green, lineWidth: 2)
                  }
          }
      }
      
      let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers")
      
      struct Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          let id = UUID()
          var name: String
          var kind: Kind
          var trick: String
          var profileImage: String
      
          init(_ name: String, kind: Kind, trick: String, profileImage: String) {
              self.name = name
              self.kind = kind
              self.trick = trick
              self.profileImage = profileImage
          }
      }
    • 7:05 - Custom views: Intro

      struct PetRowView: View {
          var body: some View {
             // ...
          }
      }
    • 7:14 - Custom views

      struct PetRowView: View {
          var body: some View {
              Image(whiskers.profileImage)
                  .clipShape(.circle)
                  .shadow(radius: 3)
                  .overlay {
                      Circle().stroke(.green, lineWidth: 2)
                  }
          }
      }
      
      let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers")
      
      struct Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          let id = UUID()
          var name: String
          var kind: Kind
          var trick: String
          var profileImage: String
      
          init(_ name: String, kind: Kind, trick: String, profileImage: String) {
              self.name = name
              self.kind = kind
              self.trick = trick
              self.profileImage = profileImage
          }
      }
    • 7:20 - Custom views: iteration

      struct PetRowView: View {
          var body: some View {
              HStack {
                  Image(whiskers.profileImage)
                      .clipShape(.circle)
                      .shadow(radius: 3)
                      .overlay {
                          Circle()
                              .stroke(.green, lineWidth: 2)
                      }
      
                  Text("Whiskers")
      
                  Spacer()
              }
          }
      }
      
      let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers")
      
      struct Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          let id = UUID()
          var name: String
          var kind: Kind
          var trick: String
          var profileImage: String
      
          init(_ name: String, kind: Kind, trick: String, profileImage: String) {
              self.name = name
              self.kind = kind
              self.trick = trick
              self.profileImage = profileImage
          }
      }
    • 7:24 - Custom views: view properties

      struct PetRowView: View {
          var body: some View {
              HStack {
                  profileImage
      
                  Text("Whiskers")
      
                  Spacer()
              }
          }
      
          private var profileImage: some View {
              Image(whiskers.profileImage)
                  .clipShape(.circle)
                  .shadow(radius: 3)
                  .overlay {
                      Circle().stroke(.green, lineWidth: 2)
                  }
          }
      }
      
      let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers")
      
      struct Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          let id = UUID()
          var name: String
          var kind: Kind
          var trick: String
          var profileImage: String
      
          init(_ name: String, kind: Kind, trick: String, profileImage: String) {
              self.name = name
              self.kind = kind
              self.trick = trick
              self.profileImage = profileImage
          }
      }
    • 7:34 - Custom views: complete row view

      struct PetRowView: View {
          var body: some View {
              HStack {
                  profileImage
      
                  VStack(alignment: .leading) {
                      Text("Whiskers")
                      Text("Tightrope walking")
                          .font(.subheadline)
                          .foregroundStyle(.secondary)
                  }
      
                  Spacer()
              }
          }
      
          private var profileImage: some View {
              Image(whiskers.profileImage)
                  .clipShape(.circle)
                  .shadow(radius: 3)
                  .overlay {
                      Circle().stroke(.green, lineWidth: 2)
                  }
          }
      }
      
      let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers")
      
      struct Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          let id = UUID()
          var name: String
          var kind: Kind
          var trick: String
          var profileImage: String
      
          init(_ name: String, kind: Kind, trick: String, profileImage: String) {
              self.name = name
              self.kind = kind
              self.trick = trick
              self.profileImage = profileImage
          }
      }
    • 7:41 - Custom views: input properties

      struct PetRowView: View {
          var pet: Pet
          var body: some View {
              HStack {
                  profileImage
      
                  VStack(alignment: .leading) {
                      Text(pet.name)
                      Text(pet.trick)
                          .font(.subheadline)
                          .foregroundStyle(.secondary)
                  }
      
                  Spacer()
              }
          }
      
          private var profileImage: some View {
              Image(pet.profileImage)
                  .clipShape(.circle)
                  .shadow(radius: 3)
                  .overlay {
                      Circle().stroke(pet.favoriteColor, lineWidth: 2)
                  }
          }
      }
      
      struct Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          let id = UUID()
          var name: String
          var kind: Kind
          var trick: String
          var profileImage: String
          var favoriteColor: Color
      
          init(_ name: String, kind: Kind, trick: String, profileImage: String, favoriteColor: Color) {
              self.name = name
              self.kind = kind
              self.trick = trick
              self.profileImage = profileImage
              self.favoriteColor = favoriteColor
          }
      }
    • 7:53 - Custom views: reuse

      PetRowView(pet: model.pet(named: "Whiskers"))
      
      PetRowView(pet: model.pet(named: "Roofus"))
      
      PetRowView(pet: model.pet(named: "Bubbles"))
    • 7:59 - List composition

      struct ContentView: View {
          var model: PetStore
          var body: some View {
              List(model.allPets) { pet in
                  PetRowView(pet: pet)
              }
          }
      }
      
      @Observable
      class PetStore {
          var allPets: [Pet] = [
              Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers", favoriteColor: .green),
              Pet("Roofus", kind: .dog, trick: "Home runs", profileImage: "Roofus", favoriteColor: .blue),
              Pet("Bubbles", kind: .fish, trick: "100m freestyle", profileImage: "Bubbles", favoriteColor: .orange),
              Pet("Mango", kind: .bird,  trick: "Basketball dunk", profileImage: "Mango", favoriteColor: .green),
              Pet("Ziggy", kind: .lizard, trick: "Parkour", profileImage: "Ziggy", favoriteColor: .purple),
              Pet("Sheldon", kind: .turtle, trick: "Kickflip", profileImage: "Sheldon", favoriteColor: .brown),
              Pet("Chirpy", kind: .bug, trick: "Canon in D", profileImage: "Chirpy", favoriteColor: .orange)
          ]
      }
    • 8:14 - List composition: ForEach

      struct ContentView: View {
          var model: PetStore
          var body: some View {
              List {
                  ForEach(model.allPets) { pet in
                      PetRowView(pet: pet)
                  }
              }
          }
      }
      
      @Observable
      class PetStore {
          var allPets: [Pet] = [
              Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers", favoriteColor: .green),
              Pet("Roofus", kind: .dog, trick: "Home runs", profileImage: "Roofus", favoriteColor: .blue),
              Pet("Bubbles", kind: .fish, trick: "100m freestyle", profileImage: "Bubbles", favoriteColor: .orange),
              Pet("Mango", kind: .bird,  trick: "Basketball dunk", profileImage: "Mango", favoriteColor: .green),
              Pet("Ziggy", kind: .lizard, trick: "Parkour", profileImage: "Ziggy", favoriteColor: .purple),
              Pet("Sheldon", kind: .turtle, trick: "Kickflip", profileImage: "Sheldon", favoriteColor: .brown),
              Pet("Chirpy", kind: .bug, trick: "Canon in D", profileImage: "Chirpy", favoriteColor: .orange)
          ]
      }
    • 8:27 - List composition: sections

      struct ContentView: View {
          var model: PetStore
          var body: some View {
              List {
                  Section("My Pets") {
                      ForEach(model.myPets) { pet in
                          PetRowView(pet: pet)
                      }
                  }
                  Section("Other Pets") {
                      ForEach(model.otherPets) { pet in
                          PetRowView(pet: pet)
                      }
                  }
              }
          }
      }
      
      @Observable
      class PetStore {
          var myPets: [Pet] = [
              Pet("Roofus", kind: .dog, trick: "Home runs", profileImage: "Roofus", favoriteColor: .blue),
              Pet("Sheldon", kind: .turtle, trick: "Kickflip", profileImage: "Sheldon", favoriteColor: .brown),
          ]
      
          var otherPets: [Pet] = [
              Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers", favoriteColor: .green),
              Pet("Bubbles", kind: .fish, trick: "100m freestyle", profileImage: "Bubbles", favoriteColor: .orange),
              Pet("Mango", kind: .bird,  trick: "Basketball dunk", profileImage: "Mango", favoriteColor: .green),
              Pet("Ziggy", kind: .lizard, trick: "Parkour", profileImage: "Ziggy", favoriteColor: .purple),
              Pet("Chirpy", kind: .bug, trick: "Canon in D", profileImage: "Chirpy", favoriteColor: .orange)
          ]
      }
    • 8:36 - List composition: section actions

      PetRowView(pet: pet)
          .swipeActions(edge: .leading) {
              Button("Award", systemImage: "trophy") {
                  // Give pet award
              }
              .tint(.orange)
      
              ShareLink(item: pet, preview: SharePreview("Pet", image: Image(pet.name)))
          }
    • 9:31 - View updates

      struct ContentView: View {
          var model: PetStore
          var body: some View {
              List {
                  Section("My Pets") {
                      ForEach(model.myPets) { pet in
                          row(pet: pet)
                      }
                  }
                  Section("Other Pets") {
                      ForEach(model.otherPets) { pet in
                          row(pet: pet)
                      }
                  }
              }
          }
      
          private func row(pet: Pet) -> some View {
              PetRowView(pet: pet)
                  .swipeActions(edge: .leading) {
                      Button("Award", systemImage: "trophy") {
                          pet.giveAward()
                      }
                      .tint(.orange)
      
                      ShareLink(item: pet, preview: SharePreview("Pet", image: Image(pet.name)))
                  }
          }
      }
      
      struct PetRowView: View {
          var pet: Pet
          var body: some View {
              HStack {
                  profileImage
      
                  VStack(alignment: .leading) {
                      HStack(alignment: .firstTextBaseline) {
                          Text(pet.name)
      
                          if pet.hasAward {
                              Image(systemName: "trophy.fill")
                                  .foregroundStyle(.orange)
                          }
                      }
                      Text(pet.trick)
                          .font(.subheadline)
                          .foregroundStyle(.secondary)
                  }
      
                  Spacer()
              }
          }
      
          private var profileImage: some View {
              Image(pet.profileImage)
                  .clipShape(.circle)
                  .shadow(radius: 3)
                  .overlay {
                      Circle().stroke(pet.favoriteColor, lineWidth: 2)
                  }
          }
      }
      
      @Observable
      class PetStore {
          var myPets: [Pet] = [
              Pet("Roofus", kind: .dog, trick: "Home runs", profileImage: "Roofus", favoriteColor: .blue),
              Pet("Sheldon", kind: .turtle, trick: "Kickflip", profileImage: "Sheldon", favoriteColor: .brown),
          ]
      
          var otherPets: [Pet] = [
              Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers", favoriteColor: .green),
              Pet("Bubbles", kind: .fish, trick: "100m freestyle", profileImage: "Bubbles", favoriteColor: .orange),
              Pet("Mango", kind: .bird,  trick: "Basketball dunk", profileImage: "Mango", favoriteColor: .green),
              Pet("Ziggy", kind: .lizard, trick: "Parkour", profileImage: "Ziggy", favoriteColor: .purple),
              Pet("Chirpy", kind: .bug, trick: "Canon in D", profileImage: "Chirpy", favoriteColor: .orange)
          ]
      }
      
      @Observable
      class Pet: Identifiable {
          enum Kind {
              case cat
              case dog
              case fish
              case bird
              case lizard
              case turtle
              case rabbit
              case bug
      
              var systemImage: String {
                  switch self {
                  case .cat: return "cat.fill"
                  case .dog: return "dog.fill"
                  case .fish: return "fish.fill"
                  case .bird: return "bird.fill"
                  case .lizard: return "lizard.fill"
                  case .turtle: return "tortoise.fill"
                  case .rabbit: return "rabbit.fill"
                  case .bug: return "ant.fill"
                  }
              }
          }
      
          var name: String
          var kind: Kind
          var trick: String
          var profileImage: String
          var favoriteColor: Color
          var hasAward: Bool = false
      
          init(_ name: String, kind: Kind, trick: String, profileImage: String, favoriteColor: Color) {
              self.name = name
              self.kind = kind
              self.trick = trick
              self.profileImage = profileImage
              self.favoriteColor = favoriteColor
          }
      
          func giveAward() {
              hasAward = true
          }
      }
      
      extension Pet: Transferable {
          static var transferRepresentation: some TransferRepresentation {
              ProxyRepresentation { $0.name }
          }
      }
    • 10:57 - State changes

      struct RatingView: View {
          @State var rating: Int = 5
      
          var body: some View {
              HStack {
                  Button("Decrease", systemImage: "minus.circle") {
                      rating -= 1
                  }
                  .disabled(rating == 0)
                  .labelStyle(.iconOnly)
      
                  Text(rating, format: .number.precision(.integerLength(2)))
                      .font(.title.bold())
      
                  Button("Increase", systemImage: "plus.circle") {
                      rating += 1
                  }
                  .disabled(rating == 10)
                  .labelStyle(.iconOnly)
              }
          }
      }
    • 11:51 - State changes: animation

      struct RatingView: View {
          @State var rating: Int = 5
      
          var body: some View {
              HStack {
                  Button("Decrease", systemImage: "minus.circle") {
                      withAnimation {
                          rating -= 1
                      }
                  }
                  .disabled(rating == 0)
                  .labelStyle(.iconOnly)
      
                  Text(rating, format: .number.precision(.integerLength(2)))
                      .font(.title.bold())
      
                  Button("Increase", systemImage: "plus.circle") {
                      withAnimation {
                          rating += 1
                      }
                  }
                  .disabled(rating == 10)
                  .labelStyle(.iconOnly)
              }
          }
      }
    • 12:05 - State changes: text content transition

      struct RatingView: View {
          @State var rating: Int = 5
      
          var body: some View {
              HStack {
                  Button("Decrease", systemImage: "minus.circle") {
                      withAnimation {
                          rating -= 1
                      }
                  }
                  .disabled(rating == 0)
                  .labelStyle(.iconOnly)
      
                  Text(rating, format: .number.precision(.integerLength(2)))
                      .contentTransition(.numericText(value: Double(rating)))
                      .font(.title.bold())
      
                  Button("Increase", systemImage: "plus.circle") {
                      withAnimation {
                          rating += 1
                      }
                  }
                  .disabled(rating == 10)
                  .labelStyle(.iconOnly)
              }
          }
      }
    • 12:22 - State changes: multiple state

      struct RatingContainerView: View {
          @State private var rating: Int = 5
      
          var body: some View {
              Gauge(value: Double(rating), in: 0...10) {
                  Text("Rating")
              }
              RatingView()
          }
      }
      
      struct RatingView: View {
          @State var rating: Int = 5
      
          var body: some View {
              HStack {
                  Button("Decrease", systemImage: "minus.circle") {
                      withAnimation {
                          rating -= 1
                      }
                  }
                  .disabled(rating == 0)
                  .labelStyle(.iconOnly)
      
                  Text(rating, format: .number.precision(.integerLength(2)))
                      .contentTransition(.numericText(value: Double(rating)))
                      .font(.title.bold())
      
                  Button("Increase", systemImage: "plus.circle") {
                      withAnimation {
                          rating += 1
                      }
                  }
                  .disabled(rating == 10)
                  .labelStyle(.iconOnly)
              }
          }
      }
    • 12:45 - State changes: state and binding

      struct RatingContainerView: View {
          @State private var rating: Int = 5
      
          var body: some View {
              Gauge(value: Double(rating), in: 0...10) {
                  Text("Rating")
              }
              RatingView(rating: $rating)
          }
      }
      
      struct RatingView: View {
          @Binding var rating: Int
      
          var body: some View {
              HStack {
                  Button("Decrease", systemImage: "minus.circle") {
                      withAnimation {
                          rating -= 1
                      }
                  }
                  .disabled(rating == 0)
                  .labelStyle(.iconOnly)
      
                  Text(rating, format: .number.precision(.integerLength(2)))
                      .contentTransition(.numericText(value: Double(rating)))
                      .font(.title.bold())
      
                  Button("Increase", systemImage: "plus.circle") {
                      withAnimation {
                          rating += 1
                      }
                  }
                  .disabled(rating == 10)
                  .labelStyle(.iconOnly)
              }
          }
      }
    • 14:16 - Adaptive buttons

      Button("Reward", systemImage: "trophy") {
          // Give pet award
      }
      // .buttonStyle(.borderless)
      // .buttonStyle(.bordered)
      // .buttonStyle(.borderedProminent)
    • 14:53 - Adaptive toggles

      Toggle("Nocturnal Mode", systemImage: "moon", isOn: $pet.isNocturnal)
      // .toggleStyle(.switch)
      // .toggleStyle(.checkbox)
      // .toggleStyle(.button)
    • 15:19 - Searchable

      struct PetListView: View {
          @Bindable var viewModel: PetStoreViewModel
      
          var body: some View {
              List {
                  Section("My Pets") {
                      ForEach(viewModel.myPets) { pet in
                          row(pet: pet)
                      }
                  }
                  Section("Other Pets") {
                      ForEach(viewModel.otherPets) { pet in
                          row(pet: pet)
                      }
                  }
              }
              .searchable(text: $viewModel.searchText)
          }
      
          private func row(pet: Pet) -> some View {
              PetRowView(pet: pet)
                  .swipeActions(edge: .leading) {
                      Button("Reward", systemImage: "trophy") {
                          pet.giveAward()
                      }
                      .tint(.orange)
      
                      ShareLink(item: pet, preview: SharePreview("Pet", image: Image(pet.name)))
                  }
          }
      }
      
      @Observable
      class PetStoreViewModel {
          var petStore: PetStore
          var searchText: String = ""
      
          init(petStore: PetStore) {
              self.petStore = petStore
          }
      
          var myPets: [Pet] {
              // For illustration purposes only. The filtered pets should be cached.
              petStore.myPets.filter { searchText.isEmpty || $0.name.contains(searchText) }
          }
          var otherPets: [Pet] {
              // For illustration purposes only. The filtered pets should be cached.
              petStore.otherPets.filter { searchText.isEmpty || $0.name.contains(searchText) }
          }
      }
    • 15:20 - Searchable: customization

      struct PetListView: View {
          @Bindable var viewModel: PetStoreViewModel
      
          var body: some View {
              List {
                  Section("My Pets") {
                      ForEach(viewModel.myPets) { pet in
                          row(pet: pet)
                      }
                  }
                  Section("Other Pets") {
                      ForEach(viewModel.otherPets) { pet in
                          row(pet: pet)
                      }
                  }
              }
              .searchable(text: $viewModel.searchText, editableTokens: $viewModel.searchTokens) { $token in
                  Label(token.kind.name, systemImage: token.kind.systemImage)
              }
              .searchScopes($viewModel.searchScope) {
                  Text("All Pets").tag(PetStoreViewModel.SearchScope.allPets)
                  Text("My Pets").tag(PetStoreViewModel.SearchScope.myPets)
                  Text("Other Pets").tag(PetStoreViewModel.SearchScope.otherPets)
              }
              .searchSuggestions {
                  PetSearchSuggestions(viewModel: viewModel)
              }
          }
      
          private func row(pet: Pet) -> some View {
              PetRowView(pet: pet)
                  .swipeActions(edge: .leading) {
                      Button("Reward", systemImage: "trophy") {
                          pet.giveAward()
                      }
                      .tint(.orange)
      
                      ShareLink(item: pet, preview: SharePreview("Pet", image: Image(pet.name)))
                  }
          }
      }
    • 16:58 - App definition

      @main
      struct SwiftUIEssentialsApp: App {
          var body: some Scene {
              WindowGroup {
                  ContentView()
              }
          }
      }
    • 17:15 - App definition: multiple scenes

      @main
      struct SwiftUIEssentialsApp: App {
          var body: some Scene {
              WindowGroup {
                  ContentView()
              }
      
              WindowGroup("Training History", id: "history", for: TrainingHistory.ID.self) { $id in
                  TrainingHistoryView(historyID: id)
              }
      
              WindowGroup("Pet Detail", id: "detail", for: Pet.ID.self) { $id in
                  PetDetailView(petID: id)
              }
         }
      }
    • 17:23 - Widgets

      struct ScoreboardWidget: Widget {
          var body: some WidgetConfiguration {
              // ...
          }
      }
      
      struct ScoreboardWidgetView: View {
          var petTrick: PetTrick
          
          var body: some View {
              ScoreCard(rating: petTrick.rating)
                  .overlay(alignment: .bottom) {
                      Text(petTrick.pet.name)
                          .padding()
                  }
                  .widgetURL(petTrick.pet.url)
          }
      }
    • 19:37 - Digital Crown rotation

      ScoreCardStack(rating: $rating)
         .focusable()
         #if os(watchOS)
         .digitalCrownRotation($rating, from: 0, through: 10)
         #endif

Developer Footer

  • Vídeos
  • WWDC24
  • SwiftUI essentials
  • 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