Swift macros

Swift language Mid-level Swift 5.9+ iOS 17+ Reviewed By Alok Singh

Pick the fix

Which line uses a macro that actually exists?

Options
Hint 1 of 1

Freestanding macros start with #.

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A #Preview { ContentView() }

Correct. #Preview is a freestanding macro from SwiftUI (Xcode 15+).

Why not the others?
  • B let s = #localized("greeting"). No such macro exists. Use String(localized: "greeting") with a String Catalog.
  • C #Observable final class Model {}. Observable is an attached macro, written @Observable.
  • D #Codable struct User {}. Codable is a protocol with compiler synthesis, not a macro.

30-second answer

Macros (Swift 5.9) generate code at compile time from your source. Freestanding macros start with # and produce an expression or declarations, like #Preview or #expect. Attached macros start with @ and add code to a declaration, like @Observable, @Model or @Entry. Macros run in a sandbox and can be expanded in Xcode to inspect the output.

Practise saying it · 45 s. No recording, just a timer

Explain Swift macros.

Say your answer out loud, then check which of these points you covered:

  • Compile-time code generation
  • Freestanding # vs attached @
  • Real examples
  • Sandboxed

Deep dive

Macros are defined in a separate package using SwiftSyntax.

They can't do arbitrary I/O; their input is the syntax tree.

Expand a macro in Xcode to see exactly what it generates.

Use them for boilerplate that is mechanical and well-defined.

Common mistakes

  • Inventing macros that don't exist (there is no #localized macro).
  • Writing a macro where a function or generic would do.

Senior take & follow-ups

Seniors can name real macros, explain expansion and weigh the build-time cost.

Follow-up questions

Think of your answer first, then open the hint.

  1. Why are macros sandboxed?

    Show hint

    To keep builds deterministic and secure.

  2. What is the cost of macros?

    Show hint

    Build time from SwiftSyntax, and harder debugging.

Suggest a fix if something here is wrong or out of date.