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
  • Swift 的新功能

    和我们一起了解 Swift 的更新。我们将向你展示 API 如何通过参数包和宏等功能变得更具扩展性和表现力。我们还将带你了解互操作性的改进,并分享我们如何将 Swift 的性能和安全优势扩展到从 Foundation 到服务器上的大型分布式程序等各个地方。

    Chapitres

    • 0:39 - Swift project update
    • 2:44 - Using if/else and switch statements as expressions
    • 3:52 - Result builders
    • 4:53 - type parameter packs
    • 9:34 - Swift macros
    • 19:47 - Swift foundation
    • 23:25 - Ownership
    • 27:59 - C++ interoperability
    • 32:41 - What's new in Swift Concurrency
    • 38:20 - FoundationDB: A case study

    Ressources

    • Swift CMake Examples
    • The Future of Foundation
    • Evolving Swift Project Workgroups
    • Swift Evolution
      • Vidéo HD
      • Vidéo SD

    Vidéos connexes

    WWDC23

    • Beyond the basics of structured concurrency
    • Expand on Swift macros
    • Generalize APIs with parameter packs
    • Meet SwiftData
    • Mix Swift and C++
    • What’s new in SwiftUI
    • Write Swift macros

    WWDC21

    • Swift concurrency: Behind the scenes
  • Rechercher dans cette vidéo…
    • 3:06 - Hard-to-read compound ternary expression

      let bullet =
          isRoot && (count == 0 || !willExpand) ? ""
              : count == 0    ? "- "
              : maxDepth <= 0 ? "▹ " : "▿ "
    • 3:19 - Familiar and readable chain of if statements

      let bullet =
          if isRoot && (count == 0 || !willExpand) { "" }
          else if count == 0 { "- " }
          else if maxDepth <= 0 { "▹ " }
          else { "▿ " }
    • 3:30 - Initializing a global variable or stored property

      let attributedName = AttributedString(markdown: displayName)
    • 3:46 - In 5.9, if statements can be an expression

      let attributedName = 
      				if let displayName, !displayName.isEmpty {
                  AttributedString(markdown: displayName)
              } else {
                  "Untitled"
              }
    • 4:31 - In Swift 5.7, errors may appear in a different place

      struct ContentView: View {
          enum Destination { case one, two }
      
          var body: some View {
              List {
                  NavigationLink(value: .one) { // The issue actually occurs here
                      Text("one")
                  }
                  NavigationLink(value: .two) {
                      Text("two")
                  }
              }.navigationDestination(for: Destination.self) {
                  $0.view // Error occurs here in 5.7
              }
          }
      }
    • 4:47 - In Swift 5.9, you now receive a more accurate compiler diagnostic

      struct ContentView: View {
          enum Destination { case one, two }
      
          var body: some View {
              List {
                  NavigationLink(value: .one) { //In 5.9, Errors provide a more accurate diagnostic
                      Text("one")
                  }
                  NavigationLink(value: .two) {
                      Text("two")
                  }
              }.navigationDestination(for: Destination.self) {
                  $0.view // Error occurs here in 5.7
              }
          }
      }
    • 5:47 - An API that takes a request type and evaluates it to produce a strongly typed value

      struct Request<Result> { ... }
      
      struct RequestEvaluator {
          func evaluate<Result>(_ request: Request<Result>) -> Result
      }
      
      func evaluate(_ request: Request<Bool>) -> Bool {
          return RequestEvaluator().evaluate(request)
      }
    • 6:03 - APIs that abstract over concrete types and varying number of arguments

      let value = RequestEvaluator().evaluate(request)
      
      let (x, y) = RequestEvaluator().evaluate(r1, r2)
      
      let (x, y, z) = RequestEvaluator().evaluate(r1, r2, r3)
    • 6:35 - Writing multiple overloads for the evaluate function

      func evaluate<Result>(_:) -> (Result)
      
      func evaluate<R1, R2>(_:_:) -> (R1, R2)
      
      func evaluate<R1, R2, R3>(_:_:_:) -> (R1, R2, R3)
      
      func evaluate<R1, R2, R3, R4>(_:_:_:_:)-> (R1, R2, R3, R4)
      
      func evaluate<R1, R2, R3, R4, R5>(_:_:_:_:_:) -> (R1, R2, R3, R4, R5)
      
      func evaluate<R1, R2, R3, R4, R5, R6>(_:_:_:_:_:_:) -> (R1, R2, R3, R4, R5, R6)
    • 6:47 - Overloads create an arbitrary upper bound for the number of arguments

      //This will cause a compiler error "Extra argument in call"
      let results = evaluator.evaluate(r1, r2, r3, r4, r5, r6, r7)
    • 7:12 - Individual type parameter

      <each Result>
    • 7:36 - Collapsing the same set of overloads into one single evaluate function

      func evaluate<each Result>(_: repeat Request<each Result>) -> (repeat each Result)
    • 8:21 - Calling updated evaluate function looks identical to calling an overload

      struct Request<Result> { ... }
      
      struct RequestEvaluator {
          func evaluate<each Result>(_: repeat Request<each Result>) -> (repeat each Result)
      }
      
      let results = RequestEvaluator.evaluate(r1, r2, r3)
    • 10:01 - It isn't clear why an assert function fails

      assert(max(a, b) == c)
    • 10:20 - XCTest provides an assert-equal operation

      XCAssertEqual(max(a, b), c) //XCTAssertEqual failed: ("10") is not equal to ("17")
    • 11:02 - Assert as a macro

      #assert(max(a, b) == c)
    • 11:42 - Macros are distributed as packages

      import PowerAssert
      #assert(max(a, b) == c)
    • 12:07 - Macro declaration for assert

      public macro assert(_ condition: Bool)
    • 12:26 - Uses are type checked against the parameters

      import PowerAssert
      #assert(max(a, b)) //Type 'Int' cannot be a used as a boolean; test for '!= 0' instead
    • 12:52 - A macro definition

      public macro assert(_ condition: Bool) = #externalMacro(
          module: “PowerAssertPlugin”,
          type: “PowerAssertMacro"
      )
    • 13:11 - Swift compiler passes the source code for the use of the macro

      #assert(a == b)
    • 13:14 - Compiler plugin produces new source code, which is integrated back into the Swift program

      PowerAssert.Assertion(
          "#assert(a == b)"
      ) {
          $0.capture(a, column: 8) == $0.capture(b, column: 13)
      }
    • 13:33 - Macro declarations include roles

      // Freestanding macro roles
      
      @freestanding(expression)
      public macro assert(_ condition: Bool) = #externalMacro(
          module: “PowerAssertPlugin”,
          type: “PowerAssertMacro"
      )
    • 13:53 - New Foundation Predicate APIs uses a `@freestanding(expression)` macro role

      let pred = #Predicate<Person> {
          $0.favoriteColor == .blue
      }
      
      let blueLovers = people.filter(pred)
    • 14:14 - Predicate expression macro

      // Predicate expression macro
      
      @freestanding(expression) 
      public macro Predicate<each Input>(
          _ body: (repeat each Input) -> Bool
      ) -> Predicate<repeat each Input>
    • 14:48 - Example of a commonly used enum

      enum Path {
          case relative(String)
          case absolute(String)
      }
    • 15:01 - Checking a specific case, like when filtering all absolute paths

      let absPaths = paths.filter { $0.isAbsolute }
    • 15:09 - Write an `isAbsolute` check as a computer property...

      extension Path {
          var isAbsolute: Bool {
              if case .absolute = self { true }
              else { false }
          }
      }
    • 15:12 - ...And another for `isRelative`

      extension Path {
          var isRelative: Bool {
              if case .relative = self { true }
              else { false }
          }
      }
    • 15:17 - Augmenting the enum with an attached macro

      @CaseDetection
      enum Path {
          case relative(String)
          case absolute(String)
      }
      
      let absPaths = paths.filter { $0.isAbsolute }
    • 15:36 - Macro-expanded code is normal Swift code

      enum Path {
          case relative(String)
          case absolute(String)
        
          //Expanded @CaseDetection macro integrated into the program.
          var isAbsolute: Bool {
              if case .absolute = self { true }
              else { false }
          }
      
          var isRelative: Bool {
              if case .relative = self { true }
              else { false }
          }
      }
    • 16:57 - Observation in SwiftUI prior to 5.9

      // Observation in SwiftUI
      
      final class Person: ObservableObject {
          @Published var name: String
          @Published var age: Int
          @Published var isFavorite: Bool
      }
      
      struct ContentView: View {
          @ObservedObject var person: Person
          
          var body: some View {
              Text("Hello, \(person.name)")
          }
      }
    • 17:25 - Observation now

      // Observation in SwiftUI
      
      @Observable final class Person {
          var name: String
          var age: Int
          var isFavorite: Bool
      }
      
      struct ContentView: View {
          var person: Person
          
          var body: some View {
              Text("Hello, \(person.name)")
          }
      }
    • 17:42 - Observable macro works with 3 macro roles

      @attached(member, names: ...)
      @attached(memberAttribute)
      @attached(conformance)
      public macro Observable() = #externalMacro(...).
    • 17:52 - Unexpanded macro

      @Observable final class Person {
          var name: String
          var age: Int
          var isFavorite: Bool
      }
    • 18:05 - Expanded member attribute role

      @Observable final class Person {
          var name: String
          var age: Int
          var isFavorite: Bool
        
      		internal let _$observationRegistrar = ObservationRegistrar<Person>()
          internal func access<Member>(
              keyPath: KeyPath<Person, Member>
          ) {
              _$observationRegistrar.access(self, keyPath: keyPath)
          }
          internal func withMutation<Member, T>(
              keyPath: KeyPath<Person, Member>,
              _ mutation: () throws -> T
          ) rethrows -> T {
              try _$observationRegistrar.withMutation(of: self, keyPath: keyPath, mutation)
          }
      }
    • 18:12 - Member attribute role adds `@ObservationTracked` to stored properties

      @Observable final class Person {
          @ObservationTracked var name: String
          @ObservationTracked var age: Int
          @ObservationTracked var isFavorite: Bool
        
      		internal let _$observationRegistrar = ObservationRegistrar<Person>()
          internal func access<Member>(
              keyPath: KeyPath<Person, Member>
          ) {
              _$observationRegistrar.access(self, keyPath: keyPath)
          }
          internal func withMutation<Member, T>(
              keyPath: KeyPath<Person, Member>,
              _ mutation: () throws -> T
          ) rethrows -> T {
              try _$observationRegistrar.withMutation(of: self, keyPath: keyPath, mutation)
          }
      }
    • 18:16 - The @ObservationTracked macro adds getters and setters to stored properties

      @Observable final class Person {
          @ObservationTracked var name: String { get { … } set { … } }
          @ObservationTracked var age: Int { get { … } set { … } }
          @ObservationTracked var isFavorite: Bool { get { … } set { … } }
        
      		internal let _$observationRegistrar = ObservationRegistrar<Person>()
          internal func access<Member>(
              keyPath: KeyPath<Person, Member>
          ) {
              _$observationRegistrar.access(self, keyPath: keyPath)
          }
          internal func withMutation<Member, T>(
              keyPath: KeyPath<Person, Member>,
              _ mutation: () throws -> T
          ) rethrows -> T {
              try _$observationRegistrar.withMutation(of: self, keyPath: keyPath, mutation)
          }
      }
    • 18:33 - All that Swift code is folded away in the @Observable macro

      @Observable final class Person {
          var name: String
          var age: Int
          var isFavorite: Bool
      }
    • 23:59 - A wrapper for a file descriptor

      struct FileDescriptor {
          private var fd: CInt
        
          init(descriptor: CInt) { self.fd = descriptor }
      
          func write(buffer: [UInt8]) throws {
              let written = buffer.withUnsafeBufferPointer {
                  Darwin.write(fd, $0.baseAddress, $0.count)
              }
              // ...
          }
        
          func close() {
              Darwin.close(fd)
          }
      }
    • 24:30 - The same FileDescriptor wrapper as a class

      class FileDescriptor {
          private var fd: CInt
        
          init(descriptor: CInt) { self.fd = descriptor }
      
          func write(buffer: [UInt8]) throws {
              let written = buffer.withUnsafeBufferPointer {
                  Darwin.write(fd, $0.baseAddress, $0.count)
              }
              // ...
          }
        
          func close() {
              Darwin.close(fd)
          }
          deinit {
              self.close(fd)
          }
      }
    • 25:05 - Going back to the struct

      struct FileDescriptor {
          private var fd: CInt
        
          init(descriptor: CInt) { self.fd = descriptor }
      
          func write(buffer: [UInt8]) throws {
              let written = buffer.withUnsafeBufferPointer {
                  Darwin.write(fd, $0.baseAddress, $0.count)
              }
              // ...
          }
        
          func close() {
              Darwin.close(fd)
          }
      }
    • 26:06 - Using Copyable in the FileDescriptor struct

      struct FileDescriptor: ~Copyable {
          private var fd: CInt
        
          init(descriptor: CInt) { self.fd = descriptor }
      
          func write(buffer: [UInt8]) throws {
              let written = buffer.withUnsafeBufferPointer {
                  Darwin.write(fd, $0.baseAddress, $0.count)
              }
              // ...
          }
        
          func close() {
              Darwin.close(fd)
          }
        
          deinit {
              Darwin.close(fd)
          }
      }
    • 26:35 - `close()` can also be marked as consuming

      struct FileDescriptor {
          private var fd: CInt
        
          init(descriptor: CInt) { self.fd = descriptor }
      
          func write(buffer: [UInt8]) throws {
              let written = buffer.withUnsafeBufferPointer {
                  Darwin.write(fd, $0.baseAddress, $0.count)
              }
              // ...
          }
        
          consuming func close() {
              Darwin.close(fd)
          }
        
          deinit {
              Darwin.close(fd)
          }
      }
    • 26:53 - When `close()` is called, it must be the final use

      let file = FileDescriptor(fd: descriptor)
      file.write(buffer: data)
      file.close()
    • 27:20 - Compiler errors instead of runtime failures

      let file = FileDescriptor(fd: descriptor)
      file.close() // Compiler will indicate where the consuming use is
      file.write(buffer: data) // Compiler error: 'file' used after consuming
    • 28:52 - Using C++ from Swift

      // Person.h
      struct Person {
          Person(const Person &);
          Person(Person &&);
          Person &operator=(const Person &);
          Person &operator=(Person &&);
          ~Person();
        
          std::string name;
          unsigned getAge() const;
      };
      std::vector<Person> everyone();
      
      // Client.swift
      func greetAdults() {
          for person in everyone().filter { $0.getAge() >= 18 } {
              print("Hello, \(person.name)!")
          }
      }
    • 29:51 - Using Swift from C++

      // Geometry.swift
      struct LabeledPoint {
          var x = 0.0, y = 0.0
          var label: String = “origin”
          mutating func moveBy(x deltaX: Double, y deltaY: Double) { … }
          var magnitude: Double { … }
      }
      
      // C++ client
      #include <Geometry-Swift.h>
      
      void test() {
          Point origin = Point()
          Point unit = Point::init(1.0, 1.0, “unit”)
          unit.moveBy(2, -2)
          std::cout << unit.label << “ moved to “ << unit.magnitude() << std::endl;
      }
    • 35:30 - An actor that manages a database connection

      // Custom actor executors
      
      actor MyConnection {
          private var database: UnsafeMutablePointer<sqlite3>
        
          init(filename: String) throws { … }
        
          func pruneOldEntries() { … }
          func fetchEntry<Entry>(named: String, type: Entry.Type) -> Entry? { … }
      }
      
      await connection.pruneOldEntries()
    • 35:58 - MyConnection with a serial dispatch queue and a custom executor

      actor MyConnection {
        private var database: UnsafeMutablePointer<sqlite3>
        private let queue: DispatchSerialQueue
        
        nonisolated var unownedExecutor: UnownedSerialExecutor { queue.asUnownedSerialExecutor() }
      
        init(filename: String, queue: DispatchSerialQueue) throws { … }
        
        func pruneOldEntries() { … }
        func fetchEntry<Entry>(named: String, type: Entry.Type) -> Entry? { … }
      }
      
      await connection.pruneOldEntries()
    • 36:44 - Dispatch queues conform to SerialExecutor protocol

      // Executor protocols
      
      protocol Executor: AnyObject, Sendable {
          func enqueue(_ job: consuming ExecutorJob)
      }
      
      protocol SerialExecutor: Executor {
          func asUnownedSerialExecutor() -> UnownedSerialExecutor
          func isSameExclusiveExecutionContext(other executor: Self) -> Bool
      }
      
      extension DispatchSerialQueue: SerialExecutor { … }
    • 39:22 - C++ implementation of FoundationDB's "master data" actor

      // C++ implementation of FoundationDB’s “master data” actor
      
      ACTOR Future<Void> getVersion(Reference<MasterData> self, GetCommitVersionRequest req) {
        	state std::map<UID, CommitProxyVersionReplies>::iterator proxyItr = self->lastCommitProxyVersionReplies.find(req.requestingProxy);
        	++self->getCommitVersionRequests;
      
        	if (proxyItr == self->lastCommitProxyVersionReplies.end()) {
            	req.reply.send(Never());
          	  return Void();
        	}
        	wait(proxyItr->second.latestRequestNum.whenAtLeast(req.requestNum - 1));
        
        	auto itr = proxyItr->second.replies.find(req.requestNum);
        	if (itr != proxyItr->second.replies.end()) {
          		req.reply.send(itr->second);
          		return Void();
        	}
      
        	// ...
      }
    • 40:18 - Swift implementation of FoundationDB's "master data" actor

      // Swift implementation of FoundationDB’s “master data” actor
      func getVersion(
          myself: MasterData, req: GetCommitVersionRequest
      ) async -> GetCommitVersionReply? {
          myself.getCommitVersionRequests += 1
      
          guard let lastVersionReplies = lastCommitProxyVersionReplies[req.requestingProxy] else {
              return nil
          }
      
          // ...
          var latestRequestNum = try await lastVersionReplies.latestRequestNum
                .atLeast(VersionMetricHandle.ValueType(req.requestNum - UInt64(1)))
      
          if let lastReply = lastVersionReplies.replies[req.requestNum] {
              return lastReply
          }
      }

Developer Footer

  • Vidéos
  • WWDC23
  • 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