This is the code that I currently have. Basically I want to have an optional ViewBuilder to add a conditional view, lets say an accessory view. In a kind of .overlay syntax, where you can either have or don't have an overlay.
But at the time of inserting the view that I'm getting this error
Cannot convert value of type '' to closure result type 'Content'
public struct MyView<Content: View>: View {
@State var isHidden: Bool = false
// stuff here
let content: (Int) -> Content
var additionalView: (() -> Content)?
public init(@ViewBuilder content: @escaping (Int) -> Content, additionalView: (() -> Content)? = nil) {
self.content = content
self.additionalView = additionalView
}
public var body: some View {
VStack(spacing: 0) {
ZStack {
content(selection)
}
// more stuff
if !isHidden {
if let additionalView {
additionalView()
}
// Another view
}
}
}
public func accessoryView(@ViewBuilder content: @escaping () -> Content) -> some View {
var view = self
view.additionalView = content
return view
}
}
Finally I want to call it this way.
struct MyMainView<Content: View>: View {
@StateObject var appInfo: AppInfo = AppInfo()
@ViewBuilder let content: (Int) -> Content
var body: some View {
VStack(spacing: 0) {
MyView(content: content)
.accessoryView {
AnyKindOfView()
// This is where it fails with "Cannot convert value of type 'AnyKindOfView' to closure result type 'Content'"
}
.onAppear {
//code
}
}
.environmentObject(appInfo)
}
}
What am I missing here? I have tried to create an additional, <AdditionalContent: View> for it but it doesn't seem to work.
You should indeed use an extra type parameter to identify the type of the accessory view. The accessory view will not necessarily be the same as
Contentafter all. This is how some of the built-in SwiftUI views are designed, like howLabelhas 2 type parameters representing the title and the icon.Note that the optional parameter makes Swift have a hard time inferring the
Accessorytype, so I removed it, and added a one-parameterinitin an extension whereAccessory == Never. Again, this is similar to how SwiftUI's built-in views with optional view builders work. For example, theButtoninitialisers that does not take alabelview builder are declared in an extension whereLabel == Text.For the
accessoryViewmodifier, it needs to be generic too. It should return a newMyView, with a differentAccessorytype parameter.Though I don't think this is necessary. Why not just pass in the view directly into the initialiser's
additionalViewargument?Another way is to use
AnyViewas the type of the accessory view. This involves making theinits generic as well.