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
 

Vidéos

Ouvrir le menu Fermer le menu
  • Collections
  • Toutes les vidéos
  • À propos

Plus de vidéos

  • À propos
  • Code
  • Code-along : Améliorez une app avec la concurrence Swift

    Découvrez comment optimiser l'expérience utilisateur de votre app avec la concurrence Swift en mettant à jour une app existante. Nous commencerons avec une app basée sur un main actor, puis introduirons progressivement du code asynchrone selon les besoins. Nous utiliserons des tâches pour optimiser le code s'exécutant sur le main actor et découvrirons comment paralléliser le code en déchargeant le travail en arrière-plan. Nous explorerons les avantages de la sécurité contre les conflits d'accès aux données et apprendrons à interpréter et à corriger les erreurs liées à cette sécurité. Enfin, nous montrerons comment tirer le meilleur parti de la concurrence structurée dans le contexte d'une app.

    Chapitres

    • 0:00 - Introduction
    • 2:11 - Configuration accessible de la concurrence
    • 2:51 - Architecture d’exemple d’app
    • 3:42 - Chargement asynchrone de photos depuis la photothèque
    • 9:03 - Extraction de l’autocollant et des couleurs de la photo
    • 12:30 - Exécution de tâches sur un thread d’arrière-plan
    • 15:58 - Parallélisation des tâches
    • 18:44 - Prévenir les conflits d’accès aux données avec Swift 6
    • 27:56 - Maîtriser le code asynchrone avec la concurrence structurée
    • 31:36 - Conclusion

    Ressources

    • Code-along: Elevating an app with Swift concurrency
    • Swift Migration Guide
      • Vidéo HD
      • Vidéo SD

    Vidéos connexes

    WWDC25

    • Adoptez la concurrence avec Swift
    • Découvrir la simultanéité dans SwiftUI

    WWDC23

    • Analyze hangs with Instruments
    • Beyond the basics of structured concurrency
  • Rechercher dans cette vidéo…
    • 6:29 - Asynchronously loading the selected photo from the photo library

      func loadPhoto(_ item: SelectedPhoto) async {
          var data: Data? = try? await item.loadTransferable(type: Data.self)
      
          if let cachedData = getCachedData(for: item.id) { data = cachedData }
      
          guard let data else { return }
          processedPhotos[item.id] = Image(data: data)
      
          cacheData(item.id, data)
      }
    • 6:59 - Calling an asynchronous function when the SwiftUI View appears

      StickerPlaceholder()
          .task {
              await viewModel.loadPhoto(selectedPhoto)
          }
    • 9:45 - Synchronously extracting the sticker and the colors from a photo

      func loadPhoto(_ item: SelectedPhoto) async {
          var data: Data? = try? await item.loadTransferable(type: Data.self)
      
          if let cachedData = getCachedData(for: item.id) { data = cachedData }
      
          guard let data else { return }
          processedPhotos[item.id] = PhotoProcessor().process(data: data)
      
          cacheData(item.id, data)
      }
    • 9:56 - Storing the processed photo in the dictionary

      var processedPhotos = [SelectedPhoto.ID: ProcessedPhoto]()
    • 10:45 - Displaying the sticker with a gradient background in the carousel

      import SwiftUI
      import PhotosUI
      
      struct StickerCarousel: View {
          @State var viewModel: StickerViewModel
          @State private var sheetPresented: Bool = false
      
          var body: some View {
              ScrollView(.horizontal) {
                  LazyHStack(spacing: 16) {
                      ForEach(viewModel.selection) { selectedPhoto in
                          VStack {
                              if let processedPhoto = viewModel.processedPhotos[selectedPhoto.id] {
                                  GradientSticker(processedPhoto: processedPhoto)
                              } else if viewModel.invalidPhotos.contains(selectedPhoto.id) {
                                  InvalidStickerPlaceholder()
                              } else {
                                  StickerPlaceholder()
                                      .task {
                                          await viewModel.loadPhoto(selectedPhoto)
                                      }
                              }
                          }
                          .containerRelativeFrame(.horizontal)
                      }
                  }
              }
              .configureCarousel(
                  viewModel,
                  sheetPresented: $sheetPresented
              )
              .sheet(isPresented: $sheetPresented) {
                  StickerGrid(viewModel: viewModel)
              }
          }
      }
    • 14:13 - Allowing photo processing to run on the background thread

      nonisolated struct PhotoProcessor {
       
          let colorExtractor = ColorExtractor()
      
          @concurrent
          func process(data: Data) async -> ProcessedPhoto? {
              let sticker = extractSticker(from: data)
              let colors = extractColors(from: data)
      
              guard let sticker = sticker, let colors = colors else { return nil }
      
              return ProcessedPhoto(sticker: sticker, colorScheme: colors)
          }
      
          private func extractColors(from data: Data) -> PhotoColorScheme? {
              // ...
          }
      
          private func extractSticker(from data: Data) -> Image? {
              // ...
          }
      }
    • 15:31 - Running the photo processing operations off the main thread

      func loadPhoto(_ item: SelectedPhoto) async {
          var data: Data? = try? await item.loadTransferable(type: Data.self)
      
          if let cachedData = getCachedData(for: item.id) { data = cachedData }
      
          guard let data else { return }
          processedPhotos[item.id] = await PhotoProcessor().process(data: data)
      
          cacheData(item.id, data)
      }
    • 20:55 - Running sticker and color extraction in parallel.

      nonisolated struct PhotoProcessor {
      
          @concurrent
          func process(data: Data) async -> ProcessedPhoto? {
              async let sticker = extractSticker(from: data)
              async let colors = extractColors(from: data)
      
              guard let sticker = await sticker, let colors = await colors else { return nil }
      
              return ProcessedPhoto(sticker: sticker, colorScheme: colors)
          }
      
          private func extractColors(from data: Data) -> PhotoColorScheme? {
              let colorExtractor = ColorExtractor()
              return colorExtractor.extractColors(from: data)
          }
      
          private func extractSticker(from data: Data) -> Image? {
              // ...
          }
      }
    • 24:20 - Applying the visual effect on each sticker in the carousel

      import SwiftUI
      import PhotosUI
      
      struct StickerCarousel: View {
          @State var viewModel: StickerViewModel
          @State private var sheetPresented: Bool = false
      
          var body: some View {
              ScrollView(.horizontal) {
                  LazyHStack(spacing: 16) {
                      ForEach(viewModel.selection) { selectedPhoto in
                          VStack {
                              if let processedPhoto = viewModel.processedPhotos[selectedPhoto.id] {
                                  GradientSticker(processedPhoto: processedPhoto)
                              } else if viewModel.invalidPhotos.contains(selectedPhoto.id) {
                                  InvalidStickerPlaceholder()
                              } else {
                                  StickerPlaceholder()
                                      .task {
                                          await viewModel.loadPhoto(selectedPhoto)
                                      }
                              }
                          }
                          .containerRelativeFrame(.horizontal)
                          .visualEffect { [selection = viewModel.selection] content, proxy in
                              let frame = proxy.frame(in: .scrollView(axis: .horizontal))
                              let distance = min(0, frame.minX)
                              let isLast = selectedPhoto.id == selection.last?.id
                              
                              return content
                                  .hueRotation(.degrees(frame.origin.x / 10))
                                  .scaleEffect(1 + distance / 700)
                                  .offset(x: isLast ? 0 : -distance / 1.25)
                                  .brightness(-distance / 400)
                                  .blur(radius: isLast ? 0 : -distance / 50)
                                  .opacity(isLast ? 1.0 : min(1.0, 1.0 - (-distance / 400)))
                          }
                      }
                  }
              }
              .configureCarousel(
                  viewModel,
                  sheetPresented: $sheetPresented
              )
              .sheet(isPresented: $sheetPresented) {
                  StickerGrid(viewModel: viewModel)
              }
          }
      }
    • 26:15 - Accessing a reference type from a concurrent task

      Task { @concurrent in
          await viewModel.loadPhoto(selectedPhoto)      
      }
    • 29:00 - Processing all photos at once with a task group

      func processAllPhotos() async {
          await withTaskGroup { group in
              for item in selection {
                  guard processedPhotos[item.id] == nil else { continue }
                  group.addTask {
                      let data = await self.getData(for: item)
                      let photo = await PhotoProcessor().process(data: data)
                      return photo.map { ProcessedPhotoResult(id: item.id, processedPhoto: $0) }
                  }
              }
      
              for await result in group {
                  if let result {
                      processedPhotos[result.id] = result.processedPhoto
                  }
              }
          }
      }
    • 30:00 - Kicking off photo processing and configuring the share link in a sticker grid view.

      import SwiftUI
      
      struct StickerGrid: View {
          let viewModel: StickerViewModel
          @State private var finishedLoading: Bool = false
      
          var body: some View {
              NavigationStack {
                  VStack {
                      if finishedLoading {
                          GridContent(viewModel: viewModel)
                      } else {
                          ProgressView()
                              .frame(maxWidth: .infinity, maxHeight: .infinity)
                              .padding()
                      }
                  }
                  .task {
                      await viewModel.processAllPhotos()
                      finishedLoading = true
                  }
                  .toolbar {
                      ToolbarItem(placement: .topBarTrailing) {
                          if finishedLoading {
                              ShareLink("Share", items: viewModel.selection.compactMap {
                                  viewModel.processedPhotos[$0.id]?.sticker
                              }) { sticker in
                                  SharePreview(
                                      "Sticker Preview",
                                      image: sticker,
                                      icon: Image(systemName: "photo")
                                  )
                              }
                          }
                      }
                  }
                  .configureStickerGrid()
              }
          }
      }

Developer Footer

  • Vidéos
  • WWDC25
  • Code-along : Améliorez une app avec la concurrence Swift
  • 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