Home > Mobile >  Swift Generic ViewModifier
Swift Generic ViewModifier

Time:09-02

I'm trying to create a generic view modifier I can use for rapid prototyping.

struct If : ViewModifier {
    var test: Bool
    var then: (_: Content) -> Content
    @ViewBuilder func body(content: Content) -> some View {
        if test {
            then(content)
        } else {
            content
        }
    }
}

What's the proper incantation to apply it to an element in the view?

struct ExampleView: View {
    var isActive: Bool
    HStack {}.modifier(If(test: isActive, then: ??? ))
}

My goal here is to be able to chain function calls conditionally on HStack and other items (e.g. .frame())

CodePudding user response:

It is difficult—probably impossible—to write this as a type conforming to ViewModifier. You give this type for then:

var then: (_: Content) -> Content

However, you're usually going to want then to return a different type than it was given, because that's how modifiers generally work. For example, Text("hello") has type Text, but Text("hello").background(Color.red) has type ModifiedContent<Text, _BackgroundStyleModifier<Color>>.

We can try making the modifier generic over the type returned by then:

struct If<Then: View>: ViewModifier {
    var test: Bool

    @ViewBuilder
    var then: (_: Content) -> Then

    @ViewBuilder
    func body(content: Content) -> some View {
        if test {
            then(content)
        } else {
            content
        }
    }
}

But then we run into a problem when we try to use the modifier:

struct ExampleView: View {
    var isActive: Bool
    var body: some View {
        HStack {
        }.modifier(If(test: isActive, then: { $0.background(.red) }))
                // ^            
  • Related