Skip to content

krzysztofzablocki/Swift-Macros

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Swift Macros 🚀



Swift Macros have brought in a new wave of possibilities. The aim of this project is to curate a list of community-created Macros and associated learning resources.

A lot of use-cases my Sourcery covered before can now be implemented by Swift Macros.






If you'd like to support my work and improve your engineering workflows, check out my SwiftyStack course

Learning Resources 📚

Tools

Frameworks

  • Swift Macro Testing: Magical testing tools for Swift macros.
    • Provides assertMacro, an alternative to Apple's assertMacroExpansion that automatically snapshots macro expansions.
    • Also provides string-based matching for diagnostics and fix-its instead of manually specifying line and column numbers.
  • Macro ToolKit
    • A powerful toolkit for creating concise and expressive Swift macros.

Apple:

Dive into Swift Macros with these WWDC sessions:

  • Write Swift Macros: An introductory session on Macros, their roles, and workings with a basic example.
  • Expand Swift Macros: A deeper exploration into crafting your Macros and testing their functionality.

Other Apple Resources:

  • Macros: The Official Step-by-Step Guide to Using Macros for Compile-Time Code Generation in Swift.
  • Example Swift Macros: Check out real-world examples from Apple, like @AddCompletionHandler and @AddAsync.

Community Blogs


Macros 💻

SwiftUI

  • EnvironmentValues & EnvironmentValue: Bypass boilerplate code and swiftly support new SwiftUI Environment Keys and Values.
  • SFSymbols Macro: A Swift Macro for "type-safe" SF Symbols.
  • SF Symbols Generator: A Swift macro generating type-safe SF Symbols.
  • Prototype (WIP): Prototype generates SwiftUI Forms and Views for data structures and classes, designed to complement SwiftData Models seamlessly.
  • HexColors: Swift Macros for validating hex colors from string and hexadecimal integer literals.

Models

  • Coding Keys: Effortlessly generate CodingKeys for converting snake_case to lowerCamelCase.
  • Coding Keys: A Swift Macro for automating CodingKeys creation in Codable structs. Supports custom string mappings for properties.
  • Coding Keys: Swift macros generating customizable CodingKeys.
  • Builder pattern: Apply the Builder Pattern with ease by generating a Builder helper class, mimicking stored properties of the associated struct.
  • Buildable Macro: An attached macro for structs, classes and enums, which produces a peer struct implementing the builder pattern. Initialise your object with minimal effort using default values:
    @Buildable struct Person { ... }
    let person = PersonBuilder(age: 42).build()
  • EnhancedMirror: An experimental Mirror alternative that utilizes Swift Macros for static reflection.
  • MetaCodable: Generates Codable implementation with following features:
    • Allows custom CodingKey value declaration per variable, instead of requiring you to write for all fields.
    • Allows to create flattened model for nested CodingKey values.
    • Allows to create composition of multiple Codable types.
    • Allows to provide default value in case of decoding failures.
    • Generates member-wise initializer considering the default values.
    • Allows to create custom decoding/encoding strategies.
    • Allows specifying fallback CodingKey values for fields and cases.
    • Allows to ignore specific properties/cases from decoding/encoding.
    • Allows setting CodingKey case style per type.
    • Allows decoding/encoding any type that conform to a particular protocol.
    • Allows decoding/encoding enums and protocols with external/internal/adjacent identifier.
    • Allows decoding/encoding enums and protocols with non-String identifier or customize the identifier detection.
  • Sealed: Parsing easily Sealed Class JSON Model on Server. (ex. kotlin server)
  • MacroCodableKit: Fully self-sufficient Codable kit:
    • Implements OpenAPI allOf and oneOf specs
    • Adjusts coding keys with a simple @CodingKey annotation
    • Decodes arrays and dictionaries in a safe manner with @CustomCoding(SafeDecoding)
    • Has built-in per-property Codable strategies and is extendible for new ones.
  • SampleBuilder: The aim of @SampleBuilder is straightforward: Generate an array of sample data from your models for use in SwiftUI previews, unit tests, or any scenario that needs mock data—without the hassle of crafting it from scratch.It works with structs and enums!
    • SampleBuilderItem: If you want to customize your sample data even further for .random generator, you can use @SampleBuilderItem to specify the type of data you want to generate for each property in your model (images, prices, names, etc.).
  • CodableOptionSet: CodableOptionSet allows for easy extensions to OptionSets implementing Codable protocol.
  • ListableProperties: ListableProperties macro adds getProperties static func which returns an array of all property names in your model.
  • BuildableMacro: A set of macros simplifying setter function generation for nominal types, inspired by SwiftUI modifiers and Observation framework macros:
    • @Buildable Automates the marking of settable properties as @BuildableTracked, excluding those marked as @BuildableIgnored.
    • @BuildableTracked Generates setter functions for each marked property, allowing fluent chaining of modifications.
    • @BuildableIgnored Excludes properties from automatic setter function generation.
  • StaticArray: An allocation-less C-like fixed size arrays.
  • UserDefaultsObservation: Combines UserDefaults and the Observation Framework. Users can easily create an Observable class where properties are backed by UserDefaults and NSUbiquitousKeyValueStore.
  • LoremSwiftify: LoremSwiftify is a Macro that creates lorem ipsum data for your models

Dependency Injection

  • swift-blade: A macro powered dependency injection framework.
  • MDI: High performance dependency injection framework.
  • SwiftEnvironment: SwiftUI based Environment global dependency locator framework with macro.

Testing

  • Mockable: Provides automatic mock implementations for your protocols and an intuitive syntax that simplifies the process of mocking services and verifying invocations in your unit tests.
  • Power Assert: Adds assertions that can automatically produce information about the values being evaluated, and present it in an easily digestible form.
  • Spyable: A Swift macro that simplifies and automates the process of creating spies for testing. Using the @Spyable annotation on a protocol, the macro generates a spy class that implements the same interface as the protocol and keeps track of interactions with its methods and properties.
  • SwiftMock: A Swift framework that simplifies and automates the process of creating mock objects for testing. Using the @Mock macro on a protocol generates Mock class. You can stub methods and properties, verifying mock calls.
  • XCTestParametrizedMacro: A Swift macro that greatly simplifies testing for many parameters. It will allow you to write one test method and parametrize it with many cases. Use @Parametrize(input: ["any", "values"]) to automatically generate new test methods for all parameters.

Networking

  • SwiftRequest: SwiftRequest is a lightweight, type-safe HTTP client for Swift, streamlining the construction and execution of HTTP request build on top of Macros.
  • Papyrus: A type-safe, protocol based HTTP client - turn your APIs into Swift protocols. Includes first-class testing support with out of the box mocking.
  • SwiftNet: SwiftNet allows to create complex network request with built-in SSL/Certificate pinning, safe access token storage, automatic callback mechanism and the ability to build those requests as Combine's Publishers as well as Async/Await tasks. Framework also provides methods to test your requests easily with or without response model checks.
  • Snowdrop: Super lightweight, type-safe, protocol based framework that includes simple and fast out of the box mocking, SSL/Certificate pinning, interception mechanism and the path variable default value support to bypass Swift protocol's limitations.

Enums

  • CasePaths: @CasePathable produces key paths for enum cases, allowing enums to be used in dynamic member lookup and other generic algorithms.
  • ExtractCaseValue: A Swift macro that extracts associated values from enum cases.

Misc

  • MacroKit: A collection of macros including:
    • @PublicInit: Generate public memberwise init
    • @GenerateMock: Create a mock object for testing from a protocol
    • @KeyPathIterable: Like CaseIterable but for available keypaths on a type
    • @StaticMemberIterable: Like CaseIterable but for available static members on a type
    • More to come...
  • InitMacro: A Swift Macro implementation that generates initializers for classes and structs with support for default values, wildcards and access control.
  • AssociatedObject: A Swift Macro for adding stored properties in Extension to classes defined in external modules, etc.
    (This is implemented by wrapping objc_getAssociatedObject/objc_setAssociatedObject.)
  • AssociatedObjectMacro: A Swift Macro for convenient declaration of variables in class extensions.
  • AliasMacro: A Swift Macro for defining aliases for types, functions, or variables.
  • UtilityType: UtilityType is an innovative library designed to realize TypeScript's UtilityTypes in Swift. See more details: https://www.typescriptlang.org/docs/handbook/utility-types.html
    • @Partial,@Required: Constructs a type with all properties set to optional(@Partial) or require(@Required). This utility will return a type that represents all subsets of a given type.
    • @Pick,@Omit: Constructs a type by picking(@Pick) or removing(@Omit) the set of specific properties keys (only string literal) from attached Type.
    • @Exclude,@Extract: Constructs a type by excluding(@Exclude) or extracting(@Extract) from enum all cases.
    • @Parameters: Constructs a tuple type from the types used in the parameters of a function type.
    • @ReturnType: Constructs a type consisting of the return type of function.
  • Reuse Identifier: A Reuse Identifier Macro that is useful in generation of a reuse id for your UICollectionViewCells and UITableViewCells
  • SwiftMacros collection: A practical collection of Swift Macros that help code correctly and smartly.
  • ModifiedCopyMacro: A Swift macro for making inline copies of a struct by modifying a property.
  • DictionaryLiteralShorthandMacro: A Swfit macro for creating dictionary literals with keys as "string representations of corresponding variable names".
  • TemporaryVariable: TemporaryVariable provide a macro #info {...}. It capture most function calls and assign them to temporary variables.
  • Localizable: Localizable A macro that produces variables and methods, for your localization files. From the enumeration keys.
  • SafeDecoding: SafeDecoding A macro that implements failable decoding via custom initializer; allows auto-conformance to `Decodable`` and per-property opt-out.
  • ObfuscateMacro: A macro for obfuscating strings and make them harder to find by binary analysis.
  • MemberwiseInit: Informed by explicit developer cues, @MemberwiseInit can more often automatically provide your intended memberwise init, while following the same safe-by-default semantics underlying Swift’s memberwise initializers.
  • PropertyTracer: Library for tracing access to properties.@PropertyTraced macro makes possible to trace from which method a property has been accessed.
  • Swift Macros: Contains a collection of useful macros:
    • #symbol: Verify if SFSymbol is valid
    • #URL: Validate and return URL Object
    • #unwrap: Unwrap value.
    • @AssociatedValues: Add variables to retrieve the associated values.
    • @Singleton: Generate singleton code for struct and class.
    • More to come...
  • Migrator: Migrator is a versatile Swift package designed to streamline the execution of asynchronous tasks with dependency management on all Apple platforms. The package also includes a handy macro for semantic versioning (SemVer 2.0.0).
    • #SemanticVersion("1.2.3")

Take part in this exciting evolution in Swift. Your contributions are most welcome!