Issue #656

Lately I’ve been challenging myself to declare switch statement in SwiftUI, or in a more generalized way, execute any anonymous function that can return a View

Use Switch and Case views

Note that this approach does not work yet, as TupeView should support variadic number of contents, and also T.RawValue needs to conform to Equatable in order to check the cases.

Also in Switch statement, Content can’t be inferred

struct Case<T: RawRepresentable, Content: View>: View {
    let value: T
    let content: Content

    init(_ value: T, @ViewBuilder content: () -> Content) {
        self.value = value
        self.content = content()
    }

    var body: some View {
        content
    }
}

struct Switch<T: RawRepresentable, Content: View>: View {
    let value: T
    let cases: TupleView<Case<T, Content>>

    init(_ value: T, @ViewBuilder cases: () -> TupleView<Case<T, Content>>) {
        self.value = value
        self.cases = cases()
    }

    var body: some View {
        makeBody()
    }

    private func makeBody() -> some View {
        // TODO: Logic here
        cases
    }
}

struct UseSwitchStatement {
    let animal: Animal = .cat

    var body: some View {
        VStack {
            Switch(animal) {
                Case(Animal.cat) {
                    Text("cat")
                }
                Case(Animal.dog) {
                    Text("dog")
                }
                Case(Animal.mouse) {
                    Text("mouse")
                }
            }
        }
    }
}

Use MakeView

Another solution is to use a MakeView view, this is more generic as it can execute any functions

enum Animal: String {
    case cat
    case dog
    case mouse
}

struct MakeView: View {
    let make: () -> AnyView

    var body: some View {
        make()
    }
}

struct UseMakeView: View {
    let animal: Animal = .cat

    var body: some View {
        MakeView {
            switch self.animal {
            case .cat:
                return Text("cat").erase()
            case .dog:
                return Text("dog").erase()
            case .mouse:
                return Text("mouse").erase()
            }
        }
    }
}

Updated at 2020-05-22 20:42:14