Search code examples
swiftswiftuistateviewbuilder

SwiftUI View Builder parameter cannot change state


I am trying to create a SwiftUI view where I can pass a view builder. But by using a view builder parameter I cannot change the state. Is this due to the creation in the init method? How can I achieve my expected behaviour?

struct Card_Previews: PreviewProvider {
    
    @State
    static var bol: Bool = true
    static var previews: some View {
        Label(title: { content })
    }
    
    // Does not change the value
    private static var content: some View {
        Button(bol.description) {
            bol.toggle()
        }
    }
}


struct Label<Title>: View where Title: View {

    var body: some View {
        title
    }

    let title: Title
    public init(@ViewBuilder title: () -> Title) {
        self.title = title()
    }
}

If something is unclear pleas ask :)


Solution

  • Your problem is unrelated to @ViewBuilder, it's because bol is a State & not Binding. To solve this you need to bind the 2 properties like so:

    struct Label<Title>: View where Title: View {
    
        @Binding
        var bol: Bool
        
        var body: some View {
            HStack {
                title
                Button(bol.description) {
                    // Changes the value
                    bol.toggle()
                    print(bol.description)
                }
            }
        }
        
        let title: Title
            
        
        public init(bol: Binding<Bool>, @ViewBuilder title: () -> Title) {
            self.title = title()
            self._bol = bol
        }
    }
    

    And in Card_Previews replace Label(title: { content }) with Label(Bol: $bol, title: { content }).