Enhancements in Function Builders

This post is about enhancements in Function Builders in Swift 5.3. I wrote two articles about Function Builders in the past so you may want to check them out before continuing with this one.
Introduction to Function Builders
Create a DSL with Function Builders

UPDATE: the feature finally made it to the language and is now called Result Builders. You don’t have to annotate builders with @_functionBuilder anymore but you can now use @resultBuilder

In 2020 SwiftUI expanded the way you can use Function Builders in the DSL by introducing if let, and the switch statement.
As usual I have a simple project on GitHub with all the code.

If let

The first version of SwiftUI supported the If statement, but many times in Swift we use the if let statement so I’d say this is a nice addition.


struct ConditionalView: View {
    private var conditionalText:String?
    
    init(conditionalText:String? = nil) {
        self.conditionalText = conditionalText
    }
    
    var body: some View {
        if let text = conditionalText {
            Text("\(text)")
        }
        else {
            Text("No text provided")
        }
    }
}

Note that you don’t need to have the same type of View in the else statement.

Switch

As I said, if let is a nice addition, but I’d argue switch is even better. As you can imagine, we can use a standard Swift switch statement, and in each case we can put a different view. As for the if let statement, the view type can be different.


struct SwitchView: View {
    private var text:String
    private var type:SwitchViewType
    
    init(text:String, type:SwitchViewType) {
        self.text = text
        self.type = type
    }
    
    var body: some View {
        switch type {
        case .normal:
            ConditionalView(conditionalText: conditionalText)
        case .bold:
            Text(text).bold()
        case .italic:
            Text(text).italic()
        case .red:
            Text("following text is red")
            Text(text).foregroundColor(.red)
        }
    }
}

As you can see we can use different Views or apply modifiers to them, this is very convenient if we have very different layouts based on some internal state.

Multiple Trailing Closures

A little bonus, not related to function builders but it is a new way to write the DSL so I guess it is worth mentioning. Swift 5.3 introduced the concept of Multiple Trailing Closures, a new way to call a function with several closures.
Let’s take a Button as an example, previously you had to create it by specifying the first parameter and at the end have the usual trailing closure


Button(action: {
    condition.toggle()
}) {
    Text("This is a button")
}

Now we can have more than one trailing closure


Button {
    condition.toggle()
} label: {
    Text("Press here...")
}

This time, you have to specify the name of the argument label.
I don’t have a strong opinion about this change yet. Some people like it, some really hate this new approach.
You can use both, so pick the one that you find simpler to read.

This is the first one of my articles about WWDC 2020, happy coding 🙂