JetForMe
(Rick M)
1
I'm having a hard time figuring out how to build a SwiftUI view that takes an optional @ViewBuilder. In my case, my app shows a bunch of lists with similar styling. Some of those lists represent paged data, and I trigger a load of the next page by appending an item at the end of the current list whose .onAppear() loads the next page.
My custom list view looks like this:
struct
ItemListView<Data, ID, Content, Trigger> : View
where
Data : RandomAccessCollection,
Content : View,
ID == Data.Element.ID,
Data.Element : Identifiable,
Trigger : View
{
public typealias ContentBuilder = (Data.Element) -> Content
public typealias TriggerBuidler = () -> Trigger
public
init(_ data: Data,
@ViewBuilder content: @escaping ContentBuilder,
@ViewBuilder trigger: @escaping TriggerBuidler?) <--- error here
{
self.data = data
self.content = content
self.trigger = trigger
}
}
Unfortunately, I get Result builder attribute 'ViewBuilder' can only be applied to a parameter of function type. This seems like an awfully restrictive requirement.
There are numerous questions of this nature online, but I can't seem to make any of them work for me in (I'm building with Xcode 13 and 12.5.1)
I tried making two init methods, one that didn't take the trigger parameter, but then it can't seem to figure out the Trigger generic parameter.
Suggestions much appreciated!
There are a few solutions. SwiftUI uses multiple initializers with the lesser initializers only available in extensions constrained to EmptyView. For example, Gauge has several, one like this:
init<V>(value: V, in bounds: ClosedRange<V> = 0...1, label: () -> Label)
where CurrentValueLabel == EmptyView,
BoundsLabel == EmptyView,
MarkedValueLabels == EmptyView,
V : BinaryFloatingPoint
Instead of an optional closure you can also provide a default, such as @ViewBuilder trigger: @escaping TriggerBuilder = { EmptyView() }.
It also seems like result builders should be able support optional values in some way.
1 Like
JetForMe
(Rick M)
3
Ah, I tried that, but perhaps I needed to constrain that initializer.