Home

Awesome

@Buildable Swift Macro

@Buildable is an attached swift macro for structs, classes and enums, which produces a peer struct implementing the builder pattern. Initialise your object with minimal effort using default values.

import Buildable

@Buildable
struct Person {
    let name: String
    let age: Int
}

let person = PersonBuilder(age: 42).build()

Important! <br>- This macro is intended to be used for simple structs, enums and classes (see below limitations) <br>- Please report any issues you might encounter <br>- Please star this repository, if your project makes use of it :)

Table of Contents

Detailed Example with generated builder

import Buildable

@Buildable
struct Person {
    let name: String
    let age: Int
    let address: Address
    let hobby: String?
    let favouriteSeason: Season
    
    var likesReading: Bool {
        hobby == "Reading" 
    }
    
    static let minimumAge = 21
}

@Buildable
enum Season {
    case .winter
    case .spring
    case .summer
    case .autumn
}

@Buildable
class AppState {
    let persons: [Person]

    init(
        persons: [Person]
    ) {
        self.person = person
    }
}

let anyPerson = PersonBuilder().build()
let max = PersonBuilder(name: "Max", favouriteSeason: .summer).build()
let appState = AppStateBuilder(persons: [max]).build()

Expanded macro

struct PersonBuilder {
    var name: String = ""
    var age: Int = 0
    var address: Address = AddressBuilder().build()
    var hobby: String?
    var favouriteSeason: SeasonBuilder = SeasonBuilder().build()

    func build() -> Person {
        return Person(
            name: name,
            age: age,
            address: address,
            hobby: hobby,
            favouriteSeason: favouriteSeason
        )
    }
}

struct SeasonBuilder {
    var value: Season = .spring
    
    func build() -> Season {
        return value
    }
}

struct AppStateBuilder {
    var persons: [Person] = []

    func build() -> AppState {
        return AppState(
            persons: persons
        )
    }
}

Installation

The library can be installed using Swift Package Manager.

Motivation

I use builders in the below two scenarios. Having them generated reduces a lot of the boilerplate code:

Limitations

Builder default values

The list of default values is limited to the values specified in the below table. If a type e.x. UnknownType is not part of the list, the macro will set the default value to UnknownTypeBuilder().build(), assuming that the UnknownTypeBuilder was created somewhere else.

TypeDefault Value
UnknownTypeUnknownTypeBuilder().build()
String""
Int0
Boolfalse
Double0
Float0
DateDate()
UUIDUUID()
[AnyType][]
[AnyType:AnyType][:]
AnyType?(implicitly nil)
AnyType!(implicitly nil)
Int80
Int160
Int320
Int460
UInt0
UInt80
UInt160
UInt320
UInt460
DataData()
URLURL(string: "https://www.google.com")!
CGFloat0
CGPointCGPoint()
CGRectCGRect()
CGSizeCGSize()
CGVectorCGVector()

Roadmap

The @Buildable macro was created out of personal interest to reduce repetitive code in my own projects. I might continue developing the macro depending use cases I stumble across, though, I do not guarantee to keep the project up to date myself. Please create GitHub issues for any feature or bugfix you would like to see within the macro. Contributions or fixes from the Community are most welcome.