Home > Software engineering >  SwiftUI when can i use if statement in result builder?
SwiftUI when can i use if statement in result builder?

Time:02-18

I notice that sometimes I am able to use if-else statement in SwiftUI's result builder just fine. For example, inside a body:

struct MyView: View {
  var body: some View {
    if foo {
      Text("foo")
    } 
  }
}

However, sometimes I can't, for example, inside view modifier:

  func body(content: Content) -> some View {
    content
      .toolbar {
        if foo { Button("foo") {} }
      }
    }
  }

This above gives me error saying:

Closure containing control flow statement cannot be used with result builder 'ToolbarContentBuilder'

This is so confusing. Why are they different? When can I use if-else, and when it should be avoided (and in that case, why is it bad? and what should I do? )

Edit:

I tried to put the button under a Group {} under the toolbar. It's not working either:

      .toolbar {
        Group {
          if true { // can't put if here
            Button("foo")

Got this error:

Closure containing control flow statement cannot be used with result builder 'CommandsBuilder'

CodePudding user response:

SwiftUI uses ResultBuilder to build views. John Sundell has a good deep-dive article on them.

Whether you can use an if depends on the result builders used by the view and, specifically, whether it implements buildIf/buildOptional methods.

An implication of supporting if in a result builder is that there can be 0 views in the result.

For whatever reason, the implementers of toolbar have decided that there must be some content in a toolbar and the so result builder they have used ToolBarContentBuilder does not implement the required methods to support conditional statements.

You are right, it is a little confusing. Unfortunately the only ways to find out whether conditionals are supported in a particular context is try or to read through the documentation to find the result builder that an element uses.

CodePudding user response:

ToolbarContentBuilder does not allow if statements, it's designed to use ToolbarItemGroup, where you can use if like a regular ViewBuilder:

var body: some View {
    NavigationView {
        Text("Hello, world!")
            .toolbar {
                ToolbarItemGroup(placement: .navigationBarTrailing) {
                    if foo { Button("foo") {} }
                }
            }
    }
}
  • Related