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
  • What's new in Swift

    Join us for an update on Swift. We'll take you through performance improvements, explore more secure and extensible Swift packages, and share advancements in Swift concurrency. We'll also introduce you to Swift Regex, better generics, and other tools built into the language to help you write more flexible & expressive code.

    Ressources

    • Celebrating learning experiences from the 2021 Swift Mentorship Program
    • Contribute to Swift
    • Swift Mentorship Program
    • Diversity in Swift
      • Vidéo HD
      • Vidéo SD

    Vidéos connexes

    WWDC22

    • Create Swift Package plugins
    • Demystify parallelization in Xcode builds
    • Design protocol interfaces in Swift
    • Eliminate data races using Swift Concurrency
    • Embrace Swift generics
    • Explore more content with MusicKit
    • Improve app size and runtime performance
    • Meet distributed actors in Swift
    • Meet Swift Async Algorithms
    • Meet Swift Package plugins
    • Meet Swift Regex
    • Swift Regex: Beyond the basics
    • Visualize and optimize Swift concurrency
  • Rechercher dans cette vidéo…
    • 7:19 - Command plugins

      @main struct MyPlugin: CommandPlugin {
      
          func performCommand(context: PluginContext, arguments: [String]) throws {
              let process = try Process.run(doccExec, arguments: doccArgs)
              process.waitUntilExit()
          }
      
      }
    • 8:34 - Build tool plugins

      import PackagePlugin
      
      @main struct MyCoolPlugin: BuildToolPlugin {
          func createBuildCommands(context: TargetBuildContext) throws -> [Command] {
              // Run some command
          }
      }
    • 8:39 - Implementing a build tool plugin

      import PackagePlugin
      
      @main struct MyCoolPlugin: BuildToolPlugin {
          func createBuildCommands(context: TargetBuildContext) throws -> [Command] {
      
              let generatedSources = context.pluginWorkDirectory.appending("GeneratedSources")
      
              return [
                  .buildCommand(
                      displayName: "Running MyTool",
                      executable: try context.tool(named: "mycooltool").path,
                      arguments: ["create"],
                      outputFilesDirectory: generatedSources)
              ]
          }
      }
    • 9:23 - Module disambiguation with module aliases

      let package = Package(
              name: "MyStunningApp",
              dependencies: [
                  .package(url: "https://.../swift-metrics.git"),
                  .package(url: "https://.../swift-log.git")
              ],
              products: [
                  .executable(name: "MyStunningApp", targets: ["MyStunningApp"])
              ],
              targets: [
                  .executableTarget(
                      name: "MyStunningApp",
                      dependencies: [
                          .product(name: "Logging", 
                                   package: "swift-log"),
                          .product(name: "Metrics", 
                                   package: "swift-metrics",
                                   moduleAliases: ["Logging": "MetricsLogging"]),
        ])])
    • 9:42 - Distinguishing between modules with the same name

      // MyStunningApp
      
      import Logging           // from swift-log
      import MetricsLogging    // from swift-metrics
      
      let swiftLogger = Logging.Logger()
      
      let metricsLogger = MetricsLogging.Logger()
    • 11:09 - Example set of protocols

      public protocol NonEmptyProtocol: Collection
          where Element == C.Element, 
              Index == C.Index {
          associatedtype C: Collection
      }
      
      public protocol MultiPoint {
          associatedtype C: CoordinateSystem
          typealias P = Self.C.P
      
          associatedtype X: NonEmptyProtocol 
              where X.C: NonEmptyProtocol, 
                  X.Element == Self.P
      }
      
      public protocol CoordinateSystem {
          associatedtype P: Point where Self.P.C == Self
          associatedtype S: Size where Self.S.C == Self
          associatedtype L: Line where Self.L.C == Self
          associatedtype B: BoundingBox where Self.B.C == Self
      }
      
      public protocol Line: MultiPoint {}
      
      public protocol Size {
          associatedtype C: CoordinateSystem where Self.C.S == Self
      }
      
      public protocol BoundingBox {
          associatedtype C: CoordinateSystem
          typealias P = Self.C.P
          typealias S = Self.C.S
      }
      
      public protocol Point {
          associatedtype C: CoordinateSystem where Self.C.P == Self
      }
    • 13:14 - Memory safety in Swift

      var numbers = [3, 2, 1]
      
      numbers.removeAll(where: { number in
          number == numbers.count 
      })
    • 14:10 - Thread safety in Swift

      var numbers = [3, 2, 1]
      
      Task { numbers.append(0) } 
      
      numbers.removeLast()
    • 15:54 - A distributed actor player and a distributed function

      distributed actor Player {
         
          var ai: PlayerBotAI?
          var gameState: GameState
          
          distributed func makeMove() -> GameMove {
              return ai.decideNextMove(given: &gameState)
          }
      }
    • 16:20 - A distributed actor call

      func endOfRound(players: [Player]) async throws {
          // Have each of the players make their move
          for player in players {
              let move = try await player.makeMove()
          }
      }
    • 20:12 - Optional unwrapping

      if let mailmapURL = mailmapURL {
      
          mailmapLines = try String(contentsOf: mailmapURL).split(separator: "\n")
          
      }
    • 20:29 - Optional unwrapping with long variable names

      if let workingDirectoryMailmapURL = workingDirectoryMailmapURL {
      
          mailmapLines = try String(contentsOf: workingDirectoryMailmapURL).split(separator: "\n")
          
      }
    • 20:35 - Cryptic abbreviated variable names

      if let wdmu = workingDirectoryMailmapURL {
      
          mailmapLines = try String(contentsOf: wdmu).split(separator: "\n")
          
      }
    • 20:46 - Unwrapping optionals in Swift 5.7

      if let workingDirectoryMailmapURL {
        
          mailmapLines = try String(contentsOf: workingDirectoryMailmapURL).split(separator: "\n")
      
      }
      
      guard let workingDirectoryMailmapURL else { return }
      
      mailmapLines = try String(contentsOf: workingDirectoryMailmapURL).split(separator: "\n")
    • 21:07 - Closure type inference

      let entries = mailmapLines.compactMap { line in
      
          try? parseLine(line)
      
      }
      
      func parseLine(_ line: Substring) throws -> MailmapEntry { … }
    • 21:33 - Type inference for complicated closures

      let entries = mailmapLines.compactMap { line in
          do {        
              return try parseLine(line)
          }
          catch {
              logger.warn("Mailmap error: \(error)")
              return nil
          }
      }
      
      
      func parseLine(_ line: Substring) throws -> MailmapEntry { … }
    • 22:15 - Mismatches that are harmless in C...

      // Mismatches that are harmless in C…
      int mailmap_get_size(mailmap_t *map);
      void mailmap_truncate(mailmap_t *map, unsigned *sizeInOut);
      
      void remove_duplicates(mailmap_t *map) {
          int size = mailmap_get_size(map);
          size -= move_duplicates_to_end(map);
          mailmap_truncate(map, &size);
      }
      
      
      // …cause problems in Swift.
      func removeDuplicates(from map: UnsafeMutablePointer<mailmap_t>) {
          var size = mailmap_get_size(map)
          size -= moveDuplicatesToEnd(map)
          mailmap_truncate(map, &size)
      }
    • 22:33 - Better interoperability with C-family code

      func removeDuplicates(from map: UnsafeMutablePointer<mailmap_t>) {
          var size = mailmap_get_size(map)
          size -= moveDuplicatesToEnd(map)
          withUnsafeMutablePointer(to: &size) { signedSizePtr in
              signedSizePtr.withMemoryRebound(to: UInt32.self, capacity: 1) { unsignedSizePtr in
                  mailmap_truncate(map, unsignedSizePtr)
              }
          }
      }
    • 23:41 - String parsing is hard

      func parseLine(_ line: Substring) throws -> MailmapEntry {
          func trim(_ str: Substring) -> Substring {
              String(str).trimmingCharacters(in: .whitespacesAndNewlines)[...]
          }
      
          let activeLine = trim(line[..<(line.firstIndex(of: "#") ?? line.endIndex)])
          guard let nameEnd = activeLine.firstIndex(of: "<"),
                let emailEnd = activeLine[nameEnd...].firstIndex(of: ">"),
                trim(activeLine[activeLine.index(after: emailEnd)...]).isEmpty else {
              throw MailmapError.badLine
          }
      
          let name = nameEnd == activeLine.startIndex ? nil : trim(activeLine[..<nameEnd])
          let email = activeLine[activeLine.index(after: nameEnd)..<emailEnd]
      
          return MailmapEntry(name: name, email: email)
      }
    • 24:05 - String parsing is still hard with better indexing

      func parseLine(_ line: Substring) throws -> MailmapEntry {
          func trim(_ str: Substring) -> Substring {
              String(str).trimmingCharacters(in: .whitespacesAndNewlines)[...]
          }
      
          let activeLine = trim(line[..<(line.firstIndex(of: "#") ?? line.endIndex)])
          guard let nameEnd = activeLine.firstIndex(of: "<"),
                let emailEnd = activeLine[nameEnd...].firstIndex(of: ">"),
                trim(activeLine[(emailEnd + 1)...]).isEmpty else {
              throw MailmapError.badLine
          }
      
          let name = nameEnd == activeLine.startIndex ? nil : trim(activeLine[..<nameEnd])
          let email = activeLine[(nameEnd + 1)..<emailEnd]
      
          return MailmapEntry(name: name, email: email)
      }
    • 24:20 - What's the problem?

      let line = "Becca Royal-Gordon <beccarg@apple.com>       # Comment"
      
      func parseLine(_ line: Substring) throws -> MailmapEntry {
          func trim(_ str: Substring) -> Substring {
              String(str).trimmingCharacters(in: .whitespacesAndNewlines)[...]
          }
      
          let activeLine = trim(line[..<(line.firstIndex(of: "#") ?? line.endIndex)])
          guard let nameEnd = activeLine.firstIndex(of: "<"),
                let emailEnd = activeLine[nameEnd...].firstIndex(of: ">"),
                trim(activeLine[activeLine.index(after: emailEnd)...]).isEmpty else {
              throw MailmapError.badLine
          }
      
          let name = nameEnd == activeLine.startIndex ? nil : trim(activeLine[..<nameEnd])
          let email = activeLine[activeLine.index(after: nameEnd)..<emailEnd]
      
          return MailmapEntry(name: name, email: email)
      }
    • 24:55 - Drawing a picture

      "Becca Royal-Gordon <beccarg@apple.com>       # Comment"
      
      /  space name space <      email      > space # or EOL /
      /  \h* ( [^<#]+? )?? \h* < ( [^>#]+ ) > \h* (?: #|\Z)  /
    • 25:10 - Swift Regex using a literal

      func parseLine(_ line: Substring) throws -> MailmapEntry {
      
          let regex = /\h*([^<#]+?)??\h*<([^>#]+)>\h*(?:#|\Z)/
      
          guard let match = line.prefixMatch(of: regex) else {
              throw MailmapError.badLine
          }
      
          return MailmapEntry(name: match.1, email: match.2)
      }
    • 25:46 - Did a cat walk across your keyboard?

      /\h*([^<#]+?)??\h*<([^>#]+)>\h*(?:#|\Z)/
    • 26:34 - Regex builder

      import RegexBuilder
      
      let regex = Regex {
          ZeroOrMore(.horizontalWhitespace)
        
          Optionally {
              Capture(OneOrMore(.noneOf("<#")))
          }
              .repetitionBehavior(.reluctant)
      
          ZeroOrMore(.horizontalWhitespace)
      
          "<"
          Capture(OneOrMore(.noneOf(">#")))
          ">"
      
          ZeroOrMore(.horizontalWhitespace)
          ChoiceOf {
             "#"
             Anchor.endOfSubjectBeforeNewline
          }
      }
    • 27:05 - Turn a regex into a reusable component

      struct MailmapLine: RegexComponent {
          @RegexComponentBuilder
          var regex: Regex<(Substring, Substring?, Substring)> {
              ZeroOrMore(.horizontalWhitespace)
      
              Optionally {
                  Capture(OneOrMore(.noneOf("<#")))
              }
                  .repetitionBehavior(.reluctant)
      
              ZeroOrMore(.horizontalWhitespace)
      
              "<"
              Capture(OneOrMore(.noneOf(">#")))
              ">"
      
              ZeroOrMore(.horizontalWhitespace)
              ChoiceOf {
                 "#"
                  Anchor.endOfSubjectBeforeNewline
              }
          }
      }
    • 27:30 - Use regex literals within a builder

      struct MailmapLine: RegexComponent {
          @RegexComponentBuilder
          var regex: Regex<(Substring, Substring?, Substring)> {
              ZeroOrMore(.horizontalWhitespace)
      
              Optionally {
                  Capture(OneOrMore(.noneOf("<#")))
              }
                  .repetitionBehavior(.reluctant)
      
              ZeroOrMore(.horizontalWhitespace)
      
              "<" 
              Capture(OneOrMore(.noneOf(">#")))
              ">" 
      
              ZeroOrMore(.horizontalWhitespace)
              /#|\Z/
         }
      }
    • 27:39 - Use Date parsers within Regex builders

      struct DatedMailmapLine: RegexComponent {
          @RegexComponentBuilder
          var regex: Regex<(Substring, Substring?, Substring, Date)> {
              ZeroOrMore(.horizontalWhitespace)
      
              Optionally {
                  Capture(OneOrMore(.noneOf("<#")))
              }
                  .repetitionBehavior(.reluctant)
      
              ZeroOrMore(.horizontalWhitespace)
      
              "<" 
              Capture(OneOrMore(.noneOf(">#")))
              ">" 
      
              ZeroOrMore(.horizontalWhitespace)
      
              Capture(.iso8601.year().month().day())
      
              ZeroOrMore(.horizontalWhitespace)
              /#|\Z/
         }
      }
    • 27:49 - Matching methods and strongly type captures in Regex

      func parseLine(_ line: Substring) throws -> MailmapEntry {
      
          let regex = /\h*([^<#]+?)??\h*<([^>#]+)>\h*(?:#|\Z)/
          // or let regex = MailmapLine()
      
          guard let match = line.prefixMatch(of: regex) else {
              throw MailmapError.badLine
          }
      
          return MailmapEntry(name: match.1, email: match.2)
      }
    • 29:02 - A use case for protocols

      /// Used in the commit list UI
      struct HashedMailmap {
          var replacementNames: [String: String] = [:]
      }
      
      /// Used in the mailmap editor UI
      struct OrderedMailmap {
          var entries: [MailmapEntry] = []
      }
      
      protocol Mailmap {
          mutating func addEntry(_ entry: MailmapEntry)
      }
      
      extension HashedMailmap: Mailmap { … }
      extension OrderedMailmap: Mailmap { … }
    • 29:26 - Using the Mailmap protocol

      func addEntries1<Map: Mailmap>(_ entries: Array<MailmapEntry>, to mailmap: inout Map) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
      
      func addEntries2(_ entries: Array<MailmapEntry>, to mailmap: inout Mailmap) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
    • 31:05 - `Mailmap` and `any Mailmap`

      func addEntries1<Map: Mailmap>(_ entries: Array<MailmapEntry>, to mailmap: inout Map) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
      
      func addEntries2(_ entries: Array<MailmapEntry>, to mailmap: inout any Mailmap) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
    • 31:17 - Improvements to `any` types

      extension Mailmap {
          mutating func mergeEntries<Other: Mailmap>(from other: Other) { … }
      }
      
      func mergeMailmaps(_ a: any Mailmap, _ b: any Mailmap) -> any Mailmap {
          var copy = a
          copy.mergeEntries(from: b)
          return a
      }
    • 32:21 - More improvements to `any` types

      protocol Mailmap: Equatable {
          mutating func addEntry(_ entry: MailmapEntry)
      }
      
      func addEntries2(_ entries: Array<MailmapEntry>, to mailmap: inout any Mailmap) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
    • 32:54 - Using Collection as an `any` type

      protocol Mailmap: Equatable {
          mutating func addEntry(_ entry: MailmapEntry)
      }
      
      func addEntries2(_ entries: any Collection<MailmapEntry>, to mailmap: inout any Mailmap) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
    • 33:04 - Primary associated types

      protocol Collection<Element>: Sequence {
          associatedtype Index: Comparable
          associatedtype Iterator: IteratorProtocol<Element>
          associatedtype SubSequence: Collection<Element>
                                          where SubSequence.Index == Index,
                                                SubSequence.SubSequence == SubSequence
      
          associatedtype Element
      }
    • 33:42 - Using primary associated types in Collection

      func addEntries1<Entries: Collection<MailmapEntry>, Map: Mailmap>(_ entries: Entries, to mailmap: inout Map) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
      
      func addEntries2(_ entries: any Collection<MailmapEntry>, to mailmap: inout any Mailmap) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
      
      extension Collection<MailmapEntry> { … }
    • 34:35 - Example of type erasing wrappers

      struct AnySprocket: Sprocket {
          private class Base { … }
          private class Box<S: Sprocket>: Base { … }
          private var box: Base
      
          // …dozens of lines of code you hate
          // having to maintain…
      }
    • 34:38 - Replace boxes with built-in `any` types

      struct AnySprocket: Sprocket {
          private var box: any Sprocket
      
          // …fewer lines of code you hate
          // having to maintain…
      }
    • 34:44 - Or try type aliases

      typealias AnySprocket = any Sprocket
    • 35:09 - `any` types have important limitations

      protocol Mailmap: Equatable {
          mutating func addEntry(_ entry: MailmapEntry)
      }
      
      func areMailmapsIdentical(_ a: any Mailmap, _ b: any Mailmap) -> Bool {
          return a == b
      }
    • 35:44 - Using generic types vs. `any` types

      func addEntries1<Entries: Collection<MailmapEntry>, Map: Mailmap>(_ entries: Entries, to mailmap: inout Map) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
      
      func addEntries2(_ entries: any Collection<MailmapEntry>, to mailmap: inout any Mailmap) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
    • 36:40 - `some Mailmap` and `any Mailmap`

      func addEntries1<Entries: Collection<MailmapEntry>>(_ entries: Entries, to mailmap: inout some Mailmap) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
      
      func addEntries2(_ entries: any Collection<MailmapEntry>, to mailmap: inout any Mailmap) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
    • 36:50 - `some Mailmap` and `any Mailmap` with Collection and primary associated types

      func addEntries1(_ entries: some Collection<MailmapEntry>, to mailmap: inout some Mailmap) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }
      
      func addEntries2(_ entries: any Collection<MailmapEntry>, to mailmap: inout any Mailmap) {
          for entry in entries {
              mailmap.addEntry(entry)
          }
      }

Developer Footer

  • Vidéos
  • WWDC22
  • What's new in 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