ShapeBuilder
A result builder implementation that allows to define shape building closures and variables.
Problem
In SwiftUI, you can end up in a situation in which you would to change a Shape
property based on a view style. Imagine, you build a view that should either take a circular appearance or have its corners rounded given a certain corner radius. Probably you would end up with something along the lines of:
However, this code doesn't compile because maskingLayer declares an opaque return type, but has no return statements in its body from which to infer an underlying type. In other words: Swift expects that maskingLayer is always of the same type.
Possible solutions
Type erasure
One way to solve this is to introduce an AnyShape type-erased helper shape and erase the return maskingLayer to AnyShape. This is a similar approach to SwiftUI's built-in AnyView type-erasing View wrapper.
As you can see, this requires us to wrap our raw shapes in AnyShape type-erasing wrappers which isn't the most beautiful code you'll ever see, but it works, doesn't it? ?♂️
Result builders to the rescue
A second approach of solving this, is to define a result builder similar to SwiftUI's own @ViewBuilder
. This library implements the @ShapeBuilder
and @InsettableShapeBuilder
result builders, allowing you to get rid of type-erasing shape wrappers and even return statements. Mark your computed property or functions with the according result builder name and you're good to go.
BuiltShape / BuiltInsettableShape
Additionally, this library provides the BuiltShape
and BuiltInsettableShape
protocols. Both protocols share similarities with SwiftUI's View
protocol. They define a get-only shape
computed property which is marked with a @ShapeBuilder
/@InsettableShapeBuilder
annotation.
This allows you to define BuiltShape
s which themselves are shapes and take the form of the shape property.
Installation
Swift Package
If you want to add ShapeBuilder to your Swift packages, add it as a dependency to your Package.swift
.
Xcode
You can add ShapeBuilder to your project via Xcode. Open your project, click on File → Swift Packages → Add Package Dependency…, enter the repository url (https://github.com/ohitsdaniel/ShapeBuilder.git) and add the package products to your app target.