Search code examples
iosswiftswiftui

What's returned from @ViewBuilder if the conditional isn't met?


I've been using @ViewBuilder like so:

@ViewBuilder
var warning: some View {
    if someWarningIsShown {
        Text("WARNING")
    }
}

This works fine, but I'm trying to figure out how @ViewBuilder works when the conditional isn't met. Since the type isn't optional I assume that something other than nil is returned. EmptyView()? AnyView(EmptyView())? What also strikes me is that there's no return keyword by the Text(). How's that even possible? I'm guessing @ViewBuilder is operating in an unconventional way. Can anyone explain?


Solution

  • This will simply just return an EmptyView. This is essentially the same as writing:

    @ViewBuilder func warning() -> some View {
        if someWarningIsShown {
            Text("WARNING")
        } else {
            EmptyView()
        }
    }
    

    If you want to write a function that allows you to return, you can simply omit the @ViewBuilder and return within your code as follows (note that all paths through the function must return a value, and all paths must return the same type of view):

    func warning() -> some View {
        if someWarningIsShown {
            return Text("WARNING")
        } else {
            return Text("SUCCESS")
        }
    }
    

    You CAN NOT write a non @ViewBuilder annotated function, that returns different types. For example, the following will return an error telling you that the function declares an opaque return type, but does not return values with the same underlying types. This is only possible with functions annotated with @ViewBuilder:

    func warning() -> some View {
        if someWarningIsShown {
            return Text("WARNING")
        } else {
            return EmptyView()
        }
    }
    

    Given the above info, we can ascertain that the @ViewBuilder attribute is doing some work under the hood that will return an EmptyView() when a block contains no statements that it can process. Digging deeper into the underlying code and the documentation we can see this to be true:

    static func buildBlock() -> EmptyView
    // Builds an empty view from a block containing no statements.