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
  • Write Swift macros

    Discover how you can use Swift macros to make your codebase more expressive and easier to read. Code along as we explore how macros can help you avoid writing repetitive code and find out how to use them in your app. We'll share the building blocks of a macro, show you how to test it, and take you through how you can emit compilation errors from macros.

    Chapitres

    • 1:15 - Overview
    • 5:10 - Create a macro using Xcode's macro template
    • 10:50 - Macro roles
    • 11:40 - Write a SlopeSubset macro to define an enum subset
    • 20:17 - Inspect the syntax tree structure in the debugger
    • 24:35 - Add a macro to an Xcode project
    • 27:05 - Emit error messages from a macro
    • 30:12 - Generalize SlopeSubset to a generic EnumSubset macro

    Ressources

      • Vidéo HD
      • Vidéo SD

    Vidéos connexes

    WWDC23

    • Discover Observation in SwiftUI
    • Expand on Swift macros
    • Swift 的新功能
    • What’s new in Xcode 15
  • Rechercher dans cette vidéo…
    • 5:55 - Invocation of the stringify macro

      import WWDC
      
      let a = 17
      let b = 25
      
      let (result, code) = #stringify(a + b)
      
      print("The value \(result) was produced by the code \"\(code)\"")
    • 6:31 - Declaration of the stringify macro

      @freestanding(expression)
      public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "WWDCMacros", type: "StringifyMacro")
    • 7:10 - Implementation of the stringify macro

      public struct StringifyMacro: ExpressionMacro {
          public static func expansion(
              of node: some FreestandingMacroExpansionSyntax,
              in context: some MacroExpansionContext
          ) -> ExprSyntax {
              guard let argument = node.argumentList.first?.expression else {
                  fatalError("compiler bug: the macro does not have any arguments")
              }
      
              return "(\(argument), \(literal: argument.description))"
          }
      }
    • 9:12 - Tests for the stringify Macro

      final class WWDCTests: XCTestCase {
          func testMacro() {
              assertMacroExpansion(
                  """
                  #stringify(a + b)
                  """,
                  expandedSource: """
                  (a + b, "a + b")
                  """,
                  macros: testMacros
              )
          }
      }
      
      let testMacros: [String: Macro.Type] = [
          "stringify": StringifyMacro.self
      ]
    • 12:05 - Slope and EasySlope

      /// Slopes in my favorite ski resort.
      enum Slope {
          case beginnersParadise
          case practiceRun
          case livingRoom
          case olympicRun
          case blackBeauty
      }
      
      /// Slopes suitable for beginners. Subset of `Slopes`.
      enum EasySlope {
          case beginnersParadise
          case practiceRun
      
          init?(_ slope: Slope) {
              switch slope {
              case .beginnersParadise: self = .beginnersParadise
              case .practiceRun: self = .practiceRun
              default: return nil
              }
          }
      
          var slope: Slope {
              switch self {
              case .beginnersParadise: return .beginnersParadise
              case .practiceRun: return .practiceRun
              }
          }
      }
    • 14:16 - Declare SlopeSubset

      /// Defines a subset of the `Slope` enum
      ///
      /// Generates two members:
      ///  - An initializer that converts a `Slope` to this type if the slope is
      ///    declared in this subset, otherwise returns `nil`
      ///  - A computed property `slope` to convert this type to a `Slope`
      ///
      /// - Important: All enum cases declared in this macro must also exist in the
      ///              `Slope` enum.
      @attached(member, names: named(init))
      public macro SlopeSubset() = #externalMacro(module: "WWDCMacros", type: "SlopeSubsetMacro")
    • 15:24 - Write empty implementation for SlopeSubset

      /// Implementation of the `SlopeSubset` macro.
      public struct SlopeSubsetMacro: MemberMacro {
          public static func expansion(
              of attribute: AttributeSyntax,
              providingMembersOf declaration: some DeclGroupSyntax,
              in context: some MacroExpansionContext
          ) throws -> [DeclSyntax] {
              return []
          }
      }
    • 16:23 - Register SlopeSubsetMacro in the compiler plugin

      @main
      struct WWDCPlugin: CompilerPlugin {
          let providingMacros: [Macro.Type] = [
              SlopeSubsetMacro.self
          ]
      }
    • 18:41 - Test SlopeSubset

      let testMacros: [String: Macro.Type] = [
          "SlopeSubset" : SlopeSubsetMacro.self,
      ]
      
      final class WWDCTests: XCTestCase {
          func testSlopeSubset() {
              assertMacroExpansion(
                  """
                  @SlopeSubset
                  enum EasySlope {
                      case beginnersParadise
                      case practiceRun
                  }
                  """, 
                  expandedSource: """
      
                  enum EasySlope {
                      case beginnersParadise
                      case practiceRun
                      init?(_ slope: Slope) {
                          switch slope {
                          case .beginnersParadise:
                              self = .beginnersParadise
                          case .practiceRun:
                              self = .practiceRun
                          default:
                              return nil
                          }
                      }
                  }
                  """, 
                  macros: testMacros
              )
          }
      }
    • 19:25 - Cast declaration to an enum declaration

      guard let enumDecl = declaration.as(EnumDeclSyntax.self) else {
          // TODO: Emit an error here
          return []
      }
    • 21:14 - Extract enum members

      let members = enumDecl.memberBlock.members
    • 21:32 - Load enum cases

      let caseDecls = members.compactMap { $0.decl.as(EnumCaseDeclSyntax.self) }
    • 21:58 - Retrieve enum elements

      let elements = caseDecls.flatMap { $0.elements }
    • 24:11 - Generate initializer

      let initializer = try InitializerDeclSyntax("init?(_ slope: Slope)") {
          try SwitchExprSyntax("switch slope") {
              for element in elements {
                  SwitchCaseSyntax(
                      """
                      case .\(element.identifier):
                          self = .\(element.identifier)
                      """
                  )
              }
              SwitchCaseSyntax("default: return nil")
          }
      }
    • 24:19 - Return generated initializer

      return [DeclSyntax(initializer)]
    • 25:51 - Apply SlopeSubset to EasySlope

      /// Slopes suitable for beginners. Subset of `Slopes`.
      @SlopeSubset
      enum EasySlope {
          case beginnersParadise
          case practiceRun
      
          var slope: Slope {
              switch self {
              case .beginnersParadise: return .beginnersParadise
              case .practiceRun: return .practiceRun
              }
          }
      }
    • 28:00 - Test that we generate an error when applying SlopeSubset to a struct

      func testSlopeSubsetOnStruct() throws {
          assertMacroExpansion(
              """
              @SlopeSubset
              struct Skier {
              }
              """,
              expandedSource: """
      
              struct Skier {
              }
              """,
              diagnostics: [
                  DiagnosticSpec(message: "@SlopeSubset can only be applied to an enum", line: 1, column: 1)
              ],
              macros: testMacros
          )
      }
    • 28:48 - Define error to emit when SlopeSubset is applied to a non-enum type

      enum SlopeSubsetError: CustomStringConvertible, Error {
          case onlyApplicableToEnum
          
          var description: String {
              switch self {
              case .onlyApplicableToEnum: return "@SlopeSubset can only be applied to an enum"
              }
          }
      }
    • 29:09 - Throw error if SlopeSubset is applied to a non-enum type

      throw SlopeSubsetError.onlyApplicableToEnum
    • 31:03 - Generalize SlopeSubset declaration to EnumSubset

      @attached(member, names: named(init))
      public macro EnumSubset<Superset>() = #externalMacro(module: "WWDCMacros", type: "SlopeSubsetMacro")
    • 31:33 - Retrieve the generic parameter of EnumSubset

      guard let supersetType = attribute
          .attributeName.as(SimpleTypeIdentifierSyntax.self)?
          .genericArgumentClause?
          .arguments.first?
          .argumentType else {
          // TODO: Handle error
          return []
      }

Developer Footer

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