SwiftUI TupleView and equally spaced stacks

Yesterday I shared with you a post where I was trying to understand SwiftUI's layout system in order to implement equally spaced distribution for views inside stacks.

I was able to do it by requiring a ForEach but I was not happy as that's not how HStack works. SwiftUI stacks allow you to nest views individually or use a ForEach. I wanted to support both systems also.

TupleView is a generic view with a tuple as its type. This allows it to keep the information of every single subview. Then I remembered some discussions on the forums about Swift not having, yet, variadic generics, and a possible solution came to my mind.

The trick is to make different init with @ViewBuilder that are overloaded on the return type of the closure.

This allows me to get access to the specific subviews of the stack, store them in an array and then add a Spacer between them in the body, in the same way that was done in the previous post.

But this journey doesn't end here. There are still a couple of things that I don't like.

To support a single subview overloading the init with a tuple of 1 element doesn't work, the TupleView needs to disappear:

// This doesnt' allow for a single subview:init<A:View>(@ViewBuilder content:()->TupleView<(A)>)// It needs this overload instead:init<A:View>(@ViewBuilder content:()-> A)

The problem with having that overload is that it's called when there are a number of subviews that we don't have another init for, so in that init we receive a TupleView and we treat it as a single view without adding spacing. Too fragile.

The other problem is that in order to gather the views they need to be wrapped in AnyView, a type erased container. (Watch Opaque Result Types to know more about this view)

So this is still not the ideal solution implementation wise, but at the API surface is what I wanted: