SwiftUI optional @ViewBuilder parameters

https://michael-ginn.medium.com/creating-optional-viewbuilder-parameters-in-swiftui-views-a0d4e3e1a0ae

Currently (June 5, 2022) in SwiftUI there is no way to have multiple optional @ViewBuilder parameters to a function. Please correct me if I'm wrong. This is a desirable feature and a common situation.

Could you explain what you want to achieve ?

Could the following meet your need?

    @ViewBuilder func destination(topic: Int) -> some View {
        switch topic {
            case 1: view1()
            case 2: view2()
            // etc
            default:EmptyView()
        }
    }

I included the link to the article explain in detail what I am trying to achieve. You need to read that short article to fully understand. However try this:

init(@ViewBuilder contentBuilder: (() -› Content)?) { }

and if you can figure that out, try to make a second parameter of the same type

Hi,

I tried to achieve the same thing, i.e. multiple optional viewbuilder parameter, and came to a solution that works well. Let's take a swipeable view where you have 3 types of content :

struct SwipeItem<Content: View, Left: View, Right: View>: View{
  private var content: () -> Content
  private var left: (() -> Left)?
  private var right: (() -> Right)?
   
  private init(@ViewBuilder content: @escaping () -> Content, left: (() -> Left)?, right: (() -> Right)?){
    self.content = content
    self.left = left
    self.right = right
  }
   
  var body: some View{
    // simplified body
    HStack{
      left?()
      content()
      right?()
    }
  }
}

You have on constructor that accept both optional parameters and you can make it private. Then you can use extensions as :

extension SwipeItem{
  init(@ViewBuilder content: @escaping () -> Content, @ViewBuilder left: @escaping () -> Left, @ViewBuilder right: @escaping () -> Right){
    self.content = content
    self.left = left
    self.right = right
  }
   
  init(@ViewBuilder content: @escaping () -> Content, @ViewBuilder left: @escaping () -> Left) where Right == EmptyView{
    self.init(content: content, left: left, right: nil)
  }
   
  init(@ViewBuilder content: @escaping () -> Content, @ViewBuilder right: @escaping () -> Right) where Left == EmptyView{
    self.init(content: content, left: nil, right: right)
  }
}

EmptyView represents the "absence" of view. So you can attach a "where" clause next to your constructor.

Then you can use it as :

struct SwipeItem_Previews: PreviewProvider{
  static var previews: some View{
    SwipeItem {
      Text("test")
    } left:{
     Text("left")
    } right: {
      Text("right")
    }

    SwipeItem {
      Text("test")
    } left:{
     Text("left")
    }
  }
}

I've been looking for a solution and found nothing to explain this (had to read a lot of docs about generics). Hope this can help.

SwiftUI optional @ViewBuilder parameters
 
 
Q