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") {} }
}
}
}
}