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
  • Protect mutable state with Swift actors

    Data races occur when two separate threads concurrently access the same mutable state. They are trivial to construct, but are notoriously hard to debug.

    Discover how you can stop these data races in their tracks with Swift actors, which help synchronize access to data in your code. Discover how actors work and how to share values between them. Learn about how actor isolation affects protocol conformances. And finally, meet the main actor, a new way of ensuring that your code always runs on the main thread when needed.

    To get the most out of this session, we recommend first watching “Meet async/await in Swift.”

    Ressources

    • SE-0316: Global actors
    • SE-0313: Improved control over actor isolation
    • SE-0306: Actors
    • SE-0302: Sendable and @Sendable closures
    • The Swift Programming Language: Concurrency
      • Vidéo HD
      • Vidéo SD

    Vidéos connexes

    WWDC22

    • Eliminate data races using Swift Concurrency
    • Meet distributed actors in Swift
    • Use Xcode for server-side development
    • Visualize and optimize Swift concurrency

    WWDC21

    • Discover concurrency in SwiftUI
    • Explore structured concurrency in Swift
    • Meet async/await in Swift
    • Swift concurrency: Behind the scenes
    • Swift concurrency: Update a sample app
    • What's new in AppKit
    • What‘s new in Swift
  • Rechercher dans cette vidéo…
    • 0:42 - Data races make concurrency hard

      class Counter {
          var value = 0
      
          func increment() -> Int {
              value = value + 1
              return value
          }
      }
      
      let counter = Counter()
      
      Task.detached {
          print(counter.increment()) // data race
      }
      
      Task.detached {
          print(counter.increment()) // data race
      }
    • 2:20 - Value semantics help eliminate data races

      var array1 = [1, 2]
      var array2 = array1
      
      array1.append(3)
      array2.append(4)
      
      print(array1)        // [1, 2, 3]
      print(array2)        // [1, 2, 4]
    • 2:59 - Sometimes shared mutable state is required

      struct Counter {
          var value = 0
      
          mutating func increment() -> Int {
              value = value + 1
              return value
          }
      }
      
      let counter = Counter()
      
      Task.detached {
          var counter = counter
          print(counter.increment()) // always prints 1
      }
      
      Task.detached {
          var counter = counter
          print(counter.increment()) // always prints 1
      }
    • 5:23 - Actor isolation prevents unsynchronized access

      actor Counter {
          var value = 0
      
          func increment() -> Int {
              value = value + 1
              return value
          }
      }
      
      let counter = Counter()
      
      Task.detached {
          print(await counter.increment())
      }
      
      Task.detached {
          print(await counter.increment())
      }
    • 7:51 - Synchronous interation within an actor

      extension Counter {
          func resetSlowly(to newValue: Int) {
              value = 0
              for _ in 0..<newValue {
                  increment()
              }
              assert(value == newValue)
          }
      }
    • 9:02 - Check your assumptions after an await: The sad cat

      actor ImageDownloader {
          private var cache: [URL: Image] = [:]
      
          func image(from url: URL) async throws -> Image? {
              if let cached = cache[url] {
                  return cached
              }
      
              let image = try await downloadImage(from: url)
      
              // Potential bug: `cache` may have changed.
              cache[url] = image
              return image
          }
      }
    • 11:50 - Check your assumptions after an await: One solution

      actor ImageDownloader {
          private var cache: [URL: Image] = [:]
      
          func image(from url: URL) async throws -> Image? {
              if let cached = cache[url] {
                  return cached
              }
      
              let image = try await downloadImage(from: url)
      
              // Replace the image only if it is still missing from the cache.
              cache[url] = cache[url, default: image]
              return cache[url]
          }
      }
    • 11:59 - Check your assumptions after an await: A better solution

      actor ImageDownloader {
      
          private enum CacheEntry {
              case inProgress(Task<Image, Error>)
              case ready(Image)
          }
      
          private var cache: [URL: CacheEntry] = [:]
      
          func image(from url: URL) async throws -> Image? {
              if let cached = cache[url] {
                  switch cached {
                  case .ready(let image):
                      return image
                  case .inProgress(let task):
                      return try await task.value
                  }
              }
      
              let task = Task {
                  try await downloadImage(from: url)
              }
      
              cache[url] = .inProgress(task)
      
              do {
                  let image = try await task.value
                  cache[url] = .ready(image)
                  return image
              } catch {
                  cache[url] = nil
                  throw error
              }
          }
      }
    • 13:30 - Protocol conformance: Static declarations are outside the actor

      actor LibraryAccount {
          let idNumber: Int
          var booksOnLoan: [Book] = []
      }
      
      extension LibraryAccount: Equatable {
          static func ==(lhs: LibraryAccount, rhs: LibraryAccount) -> Bool {
              lhs.idNumber == rhs.idNumber
          }
      }
    • 14:15 - Protocol conformance: Non-isolated declarations are outside the actor

      actor LibraryAccount {
          let idNumber: Int
          var booksOnLoan: [Book] = []
      }
      
      extension LibraryAccount: Hashable {
          nonisolated func hash(into hasher: inout Hasher) {
              hasher.combine(idNumber)
          }
      }
    • 15:32 - Closures can be isolated to the actor

      extension LibraryAccount {
          func readSome(_ book: Book) -> Int { ... }
          
          func read() -> Int {
              booksOnLoan.reduce(0) { book in
                  readSome(book)
              }
          }
      }
    • 16:29 - Closures executed in a detached task are not isolated to the actor

      extension LibraryAccount {
          func readSome(_ book: Book) -> Int { ... }
          func read() -> Int { ... }
          
          func readLater() {
              Task.detached {
                  await read()
              }
          }
      }
    • 17:15 - Passing data into and out of actors: structs

      actor LibraryAccount {
          let idNumber: Int
          var booksOnLoan: [Book] = []
          func selectRandomBook() -> Book? { ... }
      }
      
      struct Book {
          var title: String
          var authors: [Author]
      }
      
      func visit(_ account: LibraryAccount) async {
          guard var book = await account.selectRandomBook() else {
              return
          }
          book.title = "\(book.title)!!!" // OK: modifying a local copy
      }
    • 17:39 - Passing data into and out of actors: classes

      actor LibraryAccount {
          let idNumber: Int
          var booksOnLoan: [Book] = []
          func selectRandomBook() -> Book? { ... }
      }
      
      class Book {
          var title: String
          var authors: [Author]
      }
      
      func visit(_ account: LibraryAccount) async {
          guard var book = await account.selectRandomBook() else {
              return
          }
          book.title = "\(book.title)!!!" // Not OK: potential data race
      }
    • 20:08 - Check Sendable by adding a conformance

      struct Book: Sendable {
          var title: String
          var authors: [Author]
      }
    • 20:43 - Propagate Sendable by adding a conditional conformance

      struct Pair<T, U> {
          var first: T
          var second: U
      }
      
      extension Pair: Sendable where T: Sendable, U: Sendable {
      }
    • 24:19 - Interacting with the main thread: Using a DispatchQueue

      func checkedOut(_ booksOnLoan: [Book]) {
          booksView.checkedOutBooks = booksOnLoan
      }
      
      // Dispatching to the main queue is your responsibility.
      DispatchQueue.main.async {
          checkedOut(booksOnLoan)
      }
    • 25:01 - Interacting with the main thread: The main actor

      @MainActor func checkedOut(_ booksOnLoan: [Book]) {
          booksView.checkedOutBooks = booksOnLoan
      }
      
      // Swift ensures that this code is always run on the main thread.
      await checkedOut(booksOnLoan)
    • 26:21 - Main actor types

      @MainActor class MyViewController: UIViewController {
          func onPress(...) { ... } // implicitly @MainActor
      
          nonisolated func fetchLatestAndDisplay() async { ... } 
      }

Developer Footer

  • Vidéos
  • WWDC21
  • Protect mutable state with Swift actors
  • 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