{"id":23392682,"url":"https://github.com/nathantannar4/Engine","last_synced_at":"2025-08-24T11:31:05.086Z","repository":{"id":63459889,"uuid":"565300035","full_name":"nathantannar4/Engine","owner":"nathantannar4","description":"Engine makes it easier to create idiomatic APIs and Views that feel natural in SwiftUI without sacrificing performance","archived":false,"fork":false,"pushed_at":"2025-08-18T22:23:42.000Z","size":2929,"stargazers_count":422,"open_issues_count":0,"forks_count":28,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-08-18T23:38:19.921Z","etag":null,"topics":["apple","ios","iphone","macos","swift","swiftui"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nathantannar4.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-11-13T00:14:17.000Z","updated_at":"2025-08-18T22:22:29.000Z","dependencies_parsed_at":"2023-11-11T20:23:31.472Z","dependency_job_id":"ea610c32-88ab-4436-916b-e79038ddd2a0","html_url":"https://github.com/nathantannar4/Engine","commit_stats":{"total_commits":44,"total_committers":1,"mean_commits":44.0,"dds":0.0,"last_synced_commit":"284910183884d32f5ed48ebfdae345a3a1a09bcd"},"previous_names":[],"tags_count":67,"template":false,"template_full_name":null,"purl":"pkg:github/nathantannar4/Engine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathantannar4%2FEngine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathantannar4%2FEngine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathantannar4%2FEngine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathantannar4%2FEngine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nathantannar4","download_url":"https://codeload.github.com/nathantannar4/Engine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathantannar4%2FEngine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271854475,"owners_count":24834453,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-24T02:00:11.135Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apple","ios","iphone","macos","swift","swiftui"],"created_at":"2024-12-22T05:02:09.652Z","updated_at":"2025-08-24T11:31:05.069Z","avatar_url":"https://github.com/nathantannar4.png","language":"Swift","readme":"\u003cimg src=\"./Logo.png\" width=\"128\"\u003e \n\n# Engine\n\nA performance driven framework for developing SwiftUI frameworks and apps. `Engine` makes it easier to create idiomatic APIs and Views that feel natural in SwiftUI without sacrificing performance.\n\n## See Also\n\n- [Turbocharger](https://github.com/nathantannar4/Turbocharger)\n- [Ignition](https://github.com/nathantannar4/Ignition)\n- [Transmission](https://github.com/nathantannar4/Transmission)\n\n## Requirements\n\n- Deployment target: iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0 or visionOS 1.0\n- Xcode 15+\n\n## Installation\n\n### Xcode Projects\n\nSelect `File` -\u003e `Swift Packages` -\u003e `Add Package Dependency` and enter `https://github.com/nathantannar4/Engine`.\n\n### Swift Package Manager Projects\n\nYou can add `Engine` as a package dependency in your `Package.swift` file:\n\n```swift\nlet package = Package(\n    //...\n    dependencies: [\n        .package(url: \"https://github.com/nathantannar4/Engine\"),\n    ],\n    targets: [\n        .target(\n            name: \"YourPackageTarget\",\n            dependencies: [\n                .product(name: \"Engine\", package: \"Engine\"),\n                .product(name: \"EngineMacros\", package: \"Engine\"), // Optional\n            ],\n            //...\n        ),\n        //...\n    ],\n    //...\n)\n```\n\n### Xcode Cloud / Github Actions / Fastlane / CI\n\n`EngineMacros` includes a Swift macro, which requires user validation to enable or the build will fail. When configuring your CI, pass the flag `-skipMacroValidation` to `xcodebuild` to fix this.\n\n## Documentation\n\nDetailed documentation is available [here](https://swiftpackageindex.com/nathantannar4/Engine/main/documentation/engine).\n\n## Introduction to Engine\n\nFor some sample code to get started with `Engine`, build and run the included \"Example\" project.\n\n### Custom View Styles with @StyledView\n\n```swift\npublic macro StyledView()\n\n/// A protocol intended to be used with the ``@StyledView`` macro define a\n/// ``ViewStyle`` and all it's related components.\npublic protocol StyledView: View { }\n```\n\nWith the `@StyledView` macro nearly any `View` can be transformed into one that has `ViewStyle` style support. Simply attach the macro to any `StyledView`.\n\n\u003e Xcode's syntax highlighting currently does not work for types generated by a macro\n\n[Open StyledView.swift](https://github.com/nathantannar4/Engine/blob/main/Sources/Engine/Sources/StyledView.swift)\n\n#### Examples\n\n```swift\nimport EngineMacros\n\n@StyledView\nstruct LabeledView\u003cLabel: View, Content: View\u003e: StyledView {\n    var label: Label\n    var content: Content\n\n    var body: some View {\n        HStack {\n            label\n\n            content\n        }\n    }\n}\n\nextension View {\n    func labelViewStyle\u003cStyle: LabelViewStyle\u003e(_ style: Style) -\u003e some View {\n        modifier(LabelViewStyleModifier(style))\n    }\n}\n\nstruct VerticalLabeledViewStyle: LabeledViewStyle {\n    func makeBody(configuration: LabeledViewStyleConfiguration) -\u003e some View {\n        VStack {\n            configuration.label\n\n            configuration.content\n        }\n    }\n}\n\nstruct BorderedLabeledViewStyle: LabeledViewStyle {\n    func makeBody(configuration: LabeledViewStyleConfiguration) -\u003e some View {\n        LabeledView(configuration)\n            .border(Color.red)\n    }\n}\n```\n\n### Custom View Styles with ViewStyle\n\nAlternatively you can implement these manually, which is necessary for some optional features of a `ViewStyle`. For example, a `ViewStyledView` can have a `body` which is necessary to implement if you want the styled view to have a root implementation that every style would be applied on - such as a `ViewModifier` that is always added.\n\n```swift\npublic protocol ViewStyle {\n    associatedtype Configuration\n    associatedtype Body: View\n\n    @ViewBuilder\n    func makeBody(configuration: Configuration) -\u003e Body\n}\n\npublic protocol ViewStyledView: View {\n    associatedtype Configuration\n    var configuration: Configuration { get }\n\n    associatedtype DefaultStyle: ViewStyle where DefaultStyle.Configuration == Configuration\n    static var defaultStyle: DefaultStyle { get }\n}\n```\n\nA view style makes developing reusable components easier. This can be especially useful for framework developers who want a component to have a customizable appearance. Look no further than SwiftUI itself. With `Engine`, you can bring the same functionality to your app or framework by adopting the `ViewStyle` protocol. Unlike some other styling solutions you made have come across, `ViewStyle` works without relying on `AnyView` so it is very performant.\n\n[Open ViewStyle.swift](https://github.com/nathantannar4/Engine/blob/main/Sources/Engine/Sources/ViewStyle.swift)\n\n#### Examples\n\nYou can use the `ViewStyle` APIs to make components that share common behavior and/or styling, such as font/colors, while allowing for complete customization of the appearance and layout. For example, this `StepperView` is a component that defaults to `Stepper` but allows for a different custom styling to be used. \n\n```swift\n// 1. Define the style\nprotocol StepperViewStyle: ViewStyle where Configuration == StepperViewStyleConfiguration {\n}\n\n// 2. Define the style's configuration\nstruct StepperViewStyleConfiguration {\n    struct Label: ViewAlias { } // This lets the `StepperView` type erase the `Label` when used with a `StepperViewStyle`\n    var label: Label { .init() }\n\n    var onIncrement: () -\u003e Void\n    var onDecrement: () -\u003e Void\n}\n\n// 3. Define the default style\nstruct DefaultStepperViewStyle: StepperViewStyle {\n    func makeBody(configuration: StepperViewStyleConfiguration) -\u003e some View {\n        Stepper {\n            configuration.label\n        } onIncrement: {\n            configuration.onIncrement()\n        } onDecrement: {\n            configuration.onDecrement()\n        }\n    }\n}\n\n// 4. Define your custom styles\nstruct InlineStepperViewStyle: StepperViewStyle {\n    func makeBody(configuration: StepperViewStyleConfiguration) -\u003e some View {\n        HStack {\n            Button {\n                configuration.onDecrement()\n            } label: {\n                Image(systemName: \"minus.circle.fill\")\n            }\n\n            configuration.label\n\n            Button {\n                configuration.onIncrement()\n            } label: {\n                Image(systemName: \"plus.circle.fill\")\n            }\n        }\n        .accessibilityElement(children: .combine)\n        .accessibilityAdjustableAction { direction in\n            switch direction {\n            case .increment:\n                configuration.onIncrement()\n            case .decrement:\n                configuration.onDecrement()\n            default:\n                break\n            }\n        }\n    }\n}\n\n// 5. Add an extension to set the styles\nextension View {\n    func stepperViewStyle\u003cStyle: StepperViewStyle\u003e(_ style: Style) -\u003e some View {\n        styledViewStyle(StepperViewBody.self, style: style)\n    }\n}\n\n// 6. Define the component\nstruct StepperView\u003cLabel: View\u003e: View {\n    var label: Label\n    var onIncrement: () -\u003e Void\n    var onDecrement: () -\u003e Void\n\n    init(\n        @ViewBuilder label: () -\u003e Label,\n        onIncrement: @escaping () -\u003e Void,\n        onDecrement: @escaping () -\u003e Void\n    ) {\n        self.label = label()\n        self.onIncrement = onIncrement\n        self.onDecrement = onDecrement\n    }\n\n    var body: some View {\n        StepperViewBody(\n            configuration: .init(\n                onIncrement: onIncrement,\n                onDecrement: onDecrement\n            )\n        )\n        .viewAlias(StepperViewStyleConfiguration.Label.self) {\n            label\n        }\n    }\n}\n\nextension StepperView where Label == StepperViewStyleConfiguration.Label {\n    init(_ configuration: StepperViewStyleConfiguration) {\n        self.label = configuration.label\n        self.onIncrement = configuration.onIncrement\n        self.onDecrement = configuration.onDecrement\n    }\n}\n\n// 7. Define the component as a `ViewStyledView`.\nstruct StepperViewBody: ViewStyledView {\n    var configuration: StepperViewStyleConfiguration\n\n    // Implementing `body` is optional and only neccesary if you would\n    // like some default styling or modifiers that would be applied\n    // regardless of the style used\n    var body: some View {\n        StepperView(configuration)\n\t\t\t// This styling will apply to every `StepperView` regardless of the style used\n            .padding(4)\n            .background(\n                RoundedRectangle(cornerRadius: 8)\n                    .stroke(Color.secondary)\n            )\n    }\n\n    static var defaultStyle: DefaultStepperViewStyle {\n        DefaultStepperViewStyle()\n    }\n}\n\n// 8. Define a default style based on the `StyleContext` (Optional)\nstruct AutomaticStepperViewStyle: StepperViewStyle {\n    func makeBody(configuration: StepperViewStyleConfiguration) -\u003e some View {\n        StepperView(configuration)\n            .styledViewStyle(\n                StepperViewBody.self,\n                style: InlineStepperViewStyle(),\n                predicate: .scrollView // Use the inline style when in a ScrollView\n            )\n            .styledViewStyle(\n                StepperViewBody.self,\n                style: DefaultStepperViewStyle() // If no predicate matches, use the default\n            )\n    }\n}\n```\n\n[Open Examples](https://github.com/nathantannar4/Engine/blob/main/Example/Example/ViewStyleExamples.swift)\n\n### Style Context\n\n```swift\npublic protocol StyleContext {\n    /// Alternative style contexts that should also be matched against\n    static var aliases: [StyleContext.Type] { get }\n\n    /// Returns if the style context matches\n    static func evaluate(_ input: StyleContextInputs) -\u003e Bool\n}\n\n/// A modifier that applies the `Modifier` only when the`StyleContext` matches\n/// the current style context of the view.\n@frozen\npublic struct StyleContextConditionalModifier\u003c\n    Context: StyleContext,\n    Modifier: ViewModifier\n\u003e: ViewModifier {\n\n    @inlinable\n    public init(predicate: Context, @ViewModifierBuilder modifier: () -\u003e Modifier)\n}\n\n/// A modifier that statically applies the `StyleContext`to the view hierarchy.\n///\n/// See Also:\n///  - ``StyleContext``\n@frozen\npublic struct StyleContextModifier\u003c\n    Context: StyleContext\n\u003e: ViewModifier {\n\n    @inlinable\n    public init()\n}\n```\n\nA `StyleContext` can be used to conditionally apply `ViewModifier`. This is done statically, without the use of `AnyView`.\n\nSwiftUI automatically defines a `StyleContext` for views including, but not limited to, `ScrollView` and `List`. But you can also define your own `StyleContext`.\n\n#### Examples\n\n```swift\nstruct ContentView: View {\n    var body: some View {\n        ScrollView {\n            Text(\"Hello, World\")\n                .modifier(\n                    StyleContextConditionalModifier(predicate: .none) {\n                        // This modifier will not be applied\n                        BackgroundModifier(color: .red)\n                    }\n                )\n                .modifier(\n                    StyleContextConditionalModifier(predicate: .scrollView) {\n                        // This modifier would be applied\n                        BackgroundModifier(color: .blue)\n                    }\n                )\n        }\n\n        Text(\"Hello, World\")\n            .modifier(\n                StyleContextConditionalModifier(predicate: .none) {\n                    // This modifier would be applied\n                    BackgroundModifier(color: .red)\n                }\n            )\n            .modifier(\n                StyleContextConditionalModifier(predicate: .scrollView) {\n                    // This modifier will not be applied\n                    BackgroundModifier(color: .blue)\n                }\n            )\n    }\n}\n```\n\nA great usecase for `StyleContext` is when paired with custom view styles!\n\n[Open StyleContext.swift](https://github.com/nathantannar4/Engine/blob/main/Sources/Engine/Sources/StyleContext.swift)\n\n### Shapes\n\n```swift\n@frozen\npublic struct AnyShape: Shape {\n    @inlinable\n    public init\u003cS: Shape\u003e(shape: S)\n}\n\n/// A custom parameter attribute that constructs a `Shape` from closures.\n@resultBuilder\npublic struct ShapeBuilder { }\n\nextension View {\n\n    /// Sets a clipping shape for this view.\n    @inlinable\n    public func clipShape\u003cS: Shape\u003e(\n        style: FillStyle = FillStyle(),\n        @ShapeBuilder shape: () -\u003e S\n    ) -\u003e some View\n\n    /// Defines the content shape for hit testing.\n    @inlinable\n    public func contentShape\u003cS: Shape\u003e(\n        eoFill: Bool = false,\n        @ShapeBuilder shape: () -\u003e S\n    ) -\u003e some View\n\n    /// Sets the content shape for this view.\n    @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)\n    @inlinable\n    public func contentShape\u003cS: Shape\u003e(\n        _ kind: ContentShapeKinds,\n        eoFill: Bool = false,\n        @ShapeBuilder shape: () -\u003e S\n    ) -\u003e some View\n}\n```\n\nA backwards compatible `AnyShape` type erasure.\n\n### View Input\n\n```swift\npublic protocol ViewAlias: View where Body == Never {\n    associatedtype DefaultBody: View = EmptyView\n    @MainActor @ViewBuilder var defaultBody: DefaultBody { get }\n}\n\nextension View {\n\n    /// Statically type-erases `Source` to be resolved by the ``ViewAlias``.\n    @inlinable\n    public func viewAlias\u003c\n        Alias: ViewAlias,\n        Source: View\n    \u003e(\n        _ : Alias.Type,\n        @ViewBuilder source: () -\u003e Source\n    ) -\u003e some View\n}\n```\n\nA ``ViewAlias`` is can be defined statically by one of its ancestors. Because ``ViewAlias`` is guaranteed to be static it can be used for type-erasure without the performance impacts associated with `AnyView`.\n\n[Open ViewAlias.swift](https://github.com/nathantannar4/Engine/blob/main/Sources/Engine/Sources/ViewAlias.swift)\n\n### View Output\n\n```swift\n@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)\npublic protocol ViewOutputKey {\n    associatedtype Content: View = AnyView\n    typealias Value = ViewOutputList\u003cContent\u003e\n    static func reduce(value: inout Value, nextValue: () -\u003e Value)\n}\n\nextension View {\n\n    /// A modifier that writes a `Source` view to a ``ViewOutputKey``\n    @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)\n    @inlinable\n    public func viewOutput\u003c\n        Key: ViewOutputKey,\n        Source: View\n    \u003e(\n        _ : Key.Type,\n        @ViewBuilder source: () -\u003e Source\n    ) -\u003e some View where Key.Content == Source\n```\n\nA `ViewOutputKey` allows for a descendent view to return one or more views to a parent view.\n\n[Open ViewOutputKey.swift](https://github.com/nathantannar4/Engine/blob/main/Sources/Engine/Sources/ViewOutputKey.swift)  \n\n```swift\n@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)\npublic protocol ViewOutputAlias: View where Body == Never {\n    associatedtype Content: View = AnyView\n    associatedtype DefaultBody: View = EmptyView\n    @MainActor @ViewBuilder var defaultBody: DefaultBody { get }\n}\n\nextension View {\n\n    /// Statically defines the `Source` to be resolved by the ``ViewOutputAlias``.\n    @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)\n    @inlinable\n    public func viewOutputAlias\u003c\n        Alias: ViewOutputAlias,\n        Source: View\n    \u003e(\n        _ : Alias.Type,\n        @ViewBuilder source: () -\u003e Source\n    ) -\u003e some View where Alias.Content == Source\n}\n```\n\nA `ViewOutputAlias` is a more streamlined variant of `ViewOutputKey` that only supports returning a single view from a descendent. \n\n[Open ViewOutputAlias.swift](https://github.com/nathantannar4/Engine/blob/main/Sources/Engine/Sources/ViewOutputAlias.swift)\n\n### Variadic Views\n\n```swift\n@frozen\npublic struct VariadicViewAdapter\u003cSource: View, Content: View\u003e: View {\n\n    @inlinable\n    public init(\n        @ViewBuilder source: () -\u003e Source,\n        @ViewBuilder content: @escaping (VariadicView\u003cSource\u003e) -\u003e Content \n    )\n}\n```\n\nA variadic view allows many possibilities with SwiftUI to be unlocked, as it permits a transform of a single view into a collection of subviews. To learn more [MovingParts](https://movingparts.io/variadic-views-in-swiftui) has a great block post on the subject.\n\n[Open VariadicView.swift](https://github.com/nathantannar4/Engine/blob/main/Sources/Engine/Sources/VariadicView.swift)\n\n#### Examples\n\nYou can use `VariadicViewAdapter` to write components like a custom picker view.\n\n```swift\nenum Fruit: Hashable, CaseIterable {\n    case apple\n    case orange\n    case banana\n}\n\nstruct FruitPicker: View {\n    @State var selection: Fruit = .apple\n\n    var body: some View {\n        PickerView(selection: $selection) {\n            ForEach(Fruit.allCases, id: \\.self) { fruit in\n                Text(fruit.rawValue)\n            }\n        }\n        .buttonStyle(.plain)\n    }\n}\n\nstruct PickerView\u003cSelection: Hashable, Content: View\u003e: View {\n    @Binding var selection: Selection\n    @ViewBuilder var content: Content\n\n    var body: some View {\n        VariadicViewAdapter {\n            content\n        } content: { source in\n            ForEachSubview(source) { index, subview in\n                HStack {\n                    // This works since the ForEach ID is the Fruit (ie Selection) type\n                    let isSelected: Bool = selection == subview.id(as: Selection.self)\n                    if isSelected {\n                        Image(systemName: \"checkmark\")\n                    }\n\n                    Button {\n                        selection = subview.id(as: Selection.self)!\n                    } label: {\n                        subview\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n[Open Examples](https://github.com/nathantannar4/Engine/blob/main/Example/Example/VariadicViewExamples.swift)\n\n### Availability\n\n```swift\npublic protocol VersionedView: View where Body == Never {\n    associatedtype V5Body: View = V4Body\n\n    @available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, visionOS 1.0, *)\n    @ViewBuilder var v5Body: V5Body { get }\n    \n    associatedtype V4Body: View = V3Body\n\n    @available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)\n    @ViewBuilder var v4Body: V4Body { get }\n\n    associatedtype V3Body: View = V2Body\n\n    @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)\n    @ViewBuilder var v3Body: V3Body { get }\n\n    associatedtype V2Body: View = V1Body\n\n    @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)\n    @ViewBuilder var v2Body: V2Body { get }\n\n    associatedtype V1Body: View = EmptyView\n\n    @ViewBuilder var v1Body: V1Body { get }\n}\n```\n\nSupporting multiple release versions for SwiftUI can be tricky. If a modifier or view is available in a newer release, you have probably used `if #available(...)`. While this works, it is not performant since `@ViewBuilder` will turn this into an `AnyView`. Moreover, the code can become harder to read. For this reason, `Engine` has `VersionedView` and `VersionedViewModifier` for writing views with a `body` that can be different based on release availability.\n\n[Open VersionedView.swift](https://github.com/nathantannar4/Engine/blob/main/Sources/Engine/Sources/VersionedView.swift)\n\n#### Examples\n\nYou can use `VersionedViewModifier` to help adopt newer SwiftUI APIs with less friction. Such as adopting a new view type like `Grid`, while still supporting older iOS versions with a custom grid view; or using new view modifiers which due to the required `if #available(...)` checks can force you to refactor your code.\n\n```swift\nstruct ContentView: VersionedView {\n    @available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)\n    var v4Body: some View {\n        Grid {\n            // ...\n        }\n    }\n\n    var v1Body: some View {\n        CustomGridView {\n            // ...\n        }\n    }\n}\n\nstruct UnderlineModifier: VersionedViewModifier {\n    @available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)\n    func v4Body(content: Content) -\u003e some View {\n        content.underline()\n    }\n\n    // Add support for a semi-equivalent version for iOS 13-15\n    func v1Body(content: Content) -\u003e some View {\n        content\n            .background(\n                Rectangle()\n                    .frame(height: 1)\n                    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)\n            )\n    }\n}\n\nstruct UnderlineButtonStyle: ButtonStyle {\n    func makeBody(configuration: Configuration) -\u003e some View {\n        configuration.label\n            .modifier(UnderlineIfAvailableModifier()) // #if #available(...) not required\n    }\n}\n\nstruct ContentView: View {\n    var body: some View {\n        Button {\n            // ....\n        } label: {\n            Text(\"Underline if #available\")\n        }\n        .buttonStyle(UnderlineButtonStyle())\n    }\n}\n```\n\n[Open VersionedViewModifier.swift](https://github.com/nathantannar4/Engine/blob/main/Sources/Engine/Sources/VersionedViewModifier.swift)\n\n### Static Conditionals\n\n```swift\npublic protocol StaticCondition {\n    static var value: Bool { get }\n}\n\n@frozen\npublic struct StaticConditionalContent\u003c\n    Condition: StaticCondition,\n    TrueContent: View,\n    FalseContent: View\n\u003e: View {\n    \n    @inlinable\n    public init(\n        _ : Condition.Type = Condition.self,\n        @ViewBuilder then: () -\u003e TrueContent,\n        @ViewBuilder otherwise: () -\u003e FalseContent\n    )\n}\n\n@frozen\npublic struct StaticConditionalModifier\u003c\n    Condition: StaticCondition,\n    TrueModifier: ViewModifier,\n    FalseModifier: ViewModifier\n\u003e: ViewModifier {\n\n    @inlinable\n    public init(\n        _ : Condition.Type = Condition.self,\n        @ViewModifierBuilder then: () -\u003e TrueModifier,\n        @ViewModifierBuilder otherwise: () -\u003e FalseModifier\n    )\n}\n```\n\nShould you ever have a modifier or view that is conditional upon a static flag, `Engine` provides `StaticConditionalContent` and `StaticConditionalModifier`. A great example is a view or modifier is different depending on the user interface idiom. When you use an `if/else` in a `@ViewBuilder`, the Swift compiler doesn't know that the condition is static. So SwiftUI will need to be ready for the condition to change, which can hinder performance needlessly if you know the condition is static. \n\n[Open StaticConditionalContent.swift](https://github.com/nathantannar4/Engine/blob/main/Sources/Engine/Sources/StaticConditionalContent.swift)\n\n#### Examples\n\nYou can use `StaticConditionalContent` to gate features or content to Debug or Testflight builds without impacting your production build performance.\n\n```swift\nstruct IsDebug: StaticCondition {\n    static var value: Bool {\n        #if DEBUG\n        return true\n        #else\n        return false\n        #endif\n    }\n}\n\nstruct ProfileView: View {\n    var body: some View {\n        StaticConditionalContent(IsDebug.self) { // More performant than `if IsDebug.value ...`\n            NewProfileView()\n        } otherwise: {\n            LegacyProfileView()\n        }\n    }\n}\n```\n\n[Open More Examples](https://github.com/nathantannar4/Engine/blob/main/Example/Example/StaticConditionalExamples.swift)\n\n### EngineCore\n\nThe visitor pattern enables casting from a generic type T to a  protocol with an associated type so that the concrete type can be utilized.\n\n```swift\nstruct ViewAccessor: ViewVisitor {\n    var input: Any\n\n    var output: AnyView {\n        func project\u003cT\u003e(_ input: T) -\u003e AnyView {\n            var visitor = Visitor(input: input)\n            let conformance = ViewProtocolDescriptor.conformance(of: T.self)!\n            conformance.visit(visitor: \u0026visitor)\n            return visitor.output\n        }\n        return _openExistential(input, do: project)\n    }\n\n    struct Visitor\u003cT\u003e: ViewVisitor {\n        var input: T\n        var output: AnyView!\n\n        mutating func visit\u003cContent: View\u003e(type: Content.Type) {\n            let view = unsafeBitCast(input, to: Content.self)\n            output = AnyView(view)\n        }\n    }\n}\n\nlet value: Any = Text(\"Hello, World!\")\nlet accessor = ViewAccessor(input: value)\nlet view = accessor.output\nprint(view) // AnyView(Text(\"Hello, World!\"))\n```\n\n## License\n\nDistributed under the BSD 2-Clause License. See ``LICENSE.md`` for more information.\n","funding_links":[],"categories":["Swift"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnathantannar4%2FEngine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnathantannar4%2FEngine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnathantannar4%2FEngine/lists"}