A result builder that allows to define shape building closures

Related tags

Utility ShapeBuilder
Overview

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:

struct MyFancyView: View {
  let isRound: Bool

  var body: some View {
    // Fancy content here
      .mask(maskingLayer)
  }

  var maskingLayer: some Shape {
    if isRound {
      return Circle()
    } else {
      return RoundedRectangle(cornerRadius: 10)
    }
  }
}

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.

struct AnyShape: Shape {
  let _path: (CGRect) -> Path

  init<S: Shape>(_ shape: S) {
    _path = shape.path(in:)
  }

  func path(in rect: CGRect) -> Path {
    _path(rect)
  }
}

struct MyFancyView: View {
  let isRound: Bool

  var body: some View {
      // Fancy content here
        .mask(maskingLayer)
  }

  var maskingLayer: some Shape {
    if isRound {
      return AnyShape(Circle())
    } else {
      return AnyShape(RoundedRectangle(cornerRadius: 10))
    }
  }
}

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.

struct MyFancyView: View {
  let isRound: Bool

  var body: some View {
      // Fancy content here
        .mask(maskingLayer)
  }

  @ShapeBuilder var maskingLayer: some Shape {
    if isRound {
      Circle()
    } else {
      RoundedRectangle(cornerRadius: 10)
    }
  }
}

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 BuiltShapes which themselves are shapes and take the form of the shape property.

struct MyFancyMask: BuiltShape {
  let isCircle: Bool

  var shape: some Shape {
    if isCircle {
      Circle()
    } else {
      RoundedRectangle(cornerRadius: 10)
    }
  }
}

Installation

Swift Package

If you want to add ShapeBuilder to your Swift packages, add it as a dependency to your Package.swift.

dependencies: [
  .package(
    url: "https://github.com/ohitsdaniel/ShapeBuilder.git",
    from: "0.1.0"
  )
],
targets: [
  .target(
    name: "MyAwesomePackage",
    dependencies: [
      "ShapeBuilder"
    ]
  )
]

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.

License

This library is released under the MIT license. See LICENSE for details.

You might also like...
IOS-Bootcamp-Examples - Learn to Swift while building apps - With IOS Development Bootcamp
IOS-Bootcamp-Examples - Learn to Swift while building apps - With IOS Development Bootcamp

IOS-Bootcamp-Examples Learn to Swift while building apps - With IOS Development

ALO sync allows you to sync resources form an ALO endpoint to your macOS file system.
ALO sync allows you to sync resources form an ALO endpoint to your macOS file system.

ALO sync allows you to sync resources form an ALO endpoint to your macOS file system. Prerequisites macOS 11 No support for search* No suppor

This is a Swift package with support for macOS that allows to start Java Jar's with the default or a custom JVM.

Jar.swift jar runner for macos Jar.swift is created and maintaned with ❥ by Sascha Muellner. What? This is a Swift package with support for macOS that

This iOS framework allows settings to be in-app in addition to or instead of being in the Settings app.
This iOS framework allows settings to be in-app in addition to or instead of being in the Settings app.

InAppSettingsKit InAppSettingsKit (IASK) is an open source framework to easily add in-app settings to your iOS or Catalyst apps. Normally iOS apps use

A basic iOS app that takes input from the user, displays it, allows changing both text color and background color.
A basic iOS app that takes input from the user, displays it, allows changing both text color and background color.

Hello-iOSApp App Description A basic iOS app that takes input from the user, displays it, allows changing both text color and background color. App Wa

Truncate - An app that allows the user to talk with a chatbot about their mental health struggles

Project Description An app that allows the user to talk with a chatbot about the

Protected is a Swift Package that allows you to specify the read and write rights for any type, depending on context by using Phantom types
Protected is a Swift Package that allows you to specify the read and write rights for any type, depending on context by using Phantom types

Protected is a Swift Package that allows you to specify the read and write rights for any type, depending on context by using Phantom types

A result builder that build HTML parser and transform HTML elements to strongly-typed result, inspired by RegexBuilder.

HTMLParserBuilder A result builder that build HTML parser and transform HTML elements to strongly-typed result, inspired by RegexBuilder. Note: Captur

Tools for SwiftUI that helps perform Path and Shape animations, such us morphing circle or shape transformations
Tools for SwiftUI that helps perform Path and Shape animations, such us morphing circle or shape transformations

SwiftUI+PathAnimations 🔵 Introduction This packages contains SimilarShape and InterpolatedShape, both can be used to achieve shapes animations with S

Define and chain Closures with Inputs and Outputs

Closure Define and chain Closures with Inputs and Outputs Examples No Scoped State let noStateCount = ClosureString, String { text in String(repea

TupleResult - A micro library that easily converts tuple result into Swift.Result

TupleResult A micro library that easily converts c-style tuple result into Swift

RResultBuilder is DSL library based on Result Builder
RResultBuilder is DSL library based on Result Builder

RResultBuilder is DSL library based on Result Builder Features Requirements Installation Usage Screenshot Example Contribute Meta Feat

A result builder for ViewModifiers

A result builder for ViewModifiers

Helps you define secure storages for your properties using Swift property wrappers.

🔐 Secure Property Storage Helps you define secure storages for your properties using Swift property wrappers. 🌟 Features All keys are hashed using S

Define UI styles in a hot-reloadable yaml or json file
Define UI styles in a hot-reloadable yaml or json file

Stylist 🎨 Stylist lets you define UI styles in a hot-reloadable external yaml or json theme file ✅ Define styles in external theme files ✅ Apply styl

🖐 Memory game with hand gesture recognition that will keep your brain in a good shape!
🖐 Memory game with hand gesture recognition that will keep your brain in a good shape!

Hands I have always been interested in how I can improve my memory in addition to reading books, and once I came across an interesting technique relat

OysterKit is a framework that provides a native Swift scanning, lexical analysis, and parsing capabilities. In addition it provides a language that can be used to rapidly define the rules used by OysterKit called STLR

OysterKit A Swift Framework for Tokenizing, Parsing, and Interpreting Languages OysterKit enables native Swift scanning, lexical analysis, and parsing

A SwiftUI implementation of Wave animating shape.
A SwiftUI implementation of Wave animating shape.

WaveAnimation A SwiftUI implementation of Wave animating shape. Preview Usage import SineWaveShape SineWaveShape(percent: 0.4, strength: 30, frequency

Owner
Daniel Peter
🥷 Mobile Engineer (iOS) // ex-Deutsche Bahn, ex-N26
Daniel Peter
RResultBuilder is DSL library based on Result Builder

RResultBuilder is DSL library based on Result Builder Features Requirements Installation Usage Screenshot Example Contribute Meta Feat

Rakuten, Inc. 24 Sep 28, 2022
A declarative, thread safe, and reentrant way to define code that should only execute at most once over the lifetime of an object.

SwiftRunOnce SwiftRunOnce allows a developer to mark a block of logic as "one-time" code – code that will execute at most once over the lifetime of an

Thumbtack 8 Aug 17, 2022
Swifty closures for UIKit and Foundation

Closures is an iOS Framework that adds closure handlers to many of the popular UIKit and Foundation classes. Although this framework is a substitute f

Vinnie Hesener 1.7k Dec 21, 2022
A Swift micro-framework to easily deal with weak references to self inside closures

WeakableSelf Context Closures are one of Swift must-have features, and Swift developers are aware of how tricky they can be when they capture the refe

Vincent Pradeilles 72 Sep 1, 2022
Extensions which helps to convert objc-style target/action to swifty closures

ActionClosurable Usage ActionClosurable extends UIControl, UIButton, UIRefreshControl, UIGestureRecognizer and UIBarButtonItem. It helps writing swift

takasek 121 Aug 11, 2022
A collection of useful result builders for Swift and Foundation value types

Swift Builders A collection of useful result builders for Swift and Foundation value types. Motivation Arrays, dictionaries, and other collection-base

David Roman 3 Oct 14, 2022
🗃 Powerful and easy to use Swift Query Builder for Vapor 3.

⚠️ This lib is DEPRECATED ⚠️ please use SwifQL with Bridges Quick Intro struct PublicUser: Codable { var name: String var petName: String

iMike 145 Sep 10, 2022
An eject button for Interface Builder to generate swift code

Eject Eject is a utility to transition from Interface Builder to programatic view layout. This is done by using code generation to create a .swift fil

Rightpoint 524 Dec 29, 2022
Swift Markdown is a Swift package for parsing, building, editing, and analyzing Markdown documents.

Swift Markdown is a Swift package for parsing, building, editing, and analyzing Markdown documents.

Apple 2k Dec 28, 2022
Tools and helpers to make building apps faster and safer.

The UBFoundation framework provides a set of useful tools and helpers to make building apps faster and safer.

Ubique 7 Dec 19, 2022