Builder is Swift builder pattern library that utilize dynamicCallable and dynamicMemberLookup as its core.
To run the example project, clone the repo, and run pod install
from the Example directory first.
- Swift 5.1 or higher (or 5.3 when using Swift Package Manager)
- iOS 10 or higher
- macOS 10.10 or higher
- tvOS 10 or higher
- watchOS 4 or higher
Builder is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'Builder', '~> 1.1.1'
- Add it using XCode menu File > Swift Package > Add Package Dependency
- Add https://github.com/hainayanda/Builder.git as Swift Package URL
- Set rules at version, with Up to Next Major option and put 1.1.1 as its version
- Click next and wait
Add as your target dependency in Package.swift
dependencies: [
.package(url: "https://github.com/hainayanda/Builder.git", .upToNextMajor(from: "1.1.1"))
]
Use it in your target as Builder
.target(
name: "MyModule",
dependencies: ["Builder"]
)
Nayanda Haberty, [email protected]
Impose is available under the MIT license. See the LICENSE file for more info.
Using Builder is simple. You just need to pass the object you want to build and assign its writable property as its a function. Example:
If you have a class like this:
class MyObject {
var string: String?
var int: Int?
var double: Double?
...
...
}
you can build it like this:
let myObject: MyObject = builder(MyObject())
.string("some string")
.int(10)
.double(1.2)
.build()
Its even can assign property of property as deep as you need, as long the property is mutable:
let myObject: MyObject = builder(MyObject())
.string("some string")
.int(10)
.double(1.2)
.subObject.string("some string")
.subObject.int(10)
.subObject.double(1.2)
.build()
There's a protocol named Buildable that allowed your object to have a bld
computed property that will return a Builder object for you to use:
let myObject: MyObject = MyBuildable().bld
.string("some string")
.int(10)
.double(1.2)
.subObject.string("some string")
.subObject.int(10)
.subObject.double(1.2)
.build()
There's a protocol named Initializable which declared like this:
public protocol Initializable {
init()
}
its just to ensure you can call builder global function by only passing its Type
:
let view: MyObjectImplementInitializable = builder(MyObjectImplementInitializable.self)
.string("some string")
.int(10)
.double(1.2)
.build()
Initializable is implementing Buildable by default
Sometimes you can mistakenly try to assigning property that immutable. By default you can always see the debugPrint output like this:
Failed to assign property keypath of MyType with property type MyPropertyType because its not writable
But it can be forgotton and became a bug in the future. So you can always force it to throw fatalError if something like this is happes by assigning errorHandling
on BuilderConfig
:
BuilderConfig.errorHandling = .fatalErrorOnAssigningLet
it will create a fatal error when immutable property is assigned, so you can always fix it before it became a problem in the future. You can always handling it manually by assigning closure:
BuilderConfig.errorHandling = .manual { message in
debugPrint("FIX THIS: \(message)")
}
You know how, just clone and do pull request