i'm currently having issues with sending a custom view through into another view as a parameter. All the other parameters work perfectly, it's just the view.
I've setup everything within a single swift file to encapsulate the enviroment to trouble shoot but i just get: Cannot convert value of type 'Text' to expected argument type 'some View'
I'm most likely just missing something obvious, but i've tried with both any/some View, as well as variants with and without the @ViewBuilder but can't seem to find a solution.
Here's my code:
//
// ProductsTabButton.swift
// RM Product Guide
//
// Created by Matthew Hardiman on 04/07/2023.
//
import SwiftUI
struct ProductsTabButton: View {
@State var sheetActiveBool: Bool = false
var dismissFunction: () -> Void
var buttonColor: String = "rmWhite"
var buttonText: String = "Button Text"
var buttonIcon: String = "list.dash"
var buttonView: some View = BackgroundView()
var body: some View {
// BUTTON STYLING
Button(action: {
sheetActiveBool.toggle()
},label:{
VStack(spacing: 0){
Image(systemName: buttonIcon).productLinkBlockImage()
Text(buttonText).productLinkBlockText()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(buttonColor))
})
.sheet(isPresented: $sheetActiveBool, onDismiss: dismissFunction) {
fetchView()
}
}
@ViewBuilder
func fetchView() -> some View {
buttonView
}
}
struct ProductsTabButton_Previews: PreviewProvider {
static var previews: some View {
ProductsTabButton(
dismissFunction: {
print("Test")
},
buttonColor: "rmYellow",
buttonText: "Yellow",
buttonIcon: "list.star",
//buttonView: SearchView()
buttonView: Text("Test")
)
}
}
Any help with this would be greatly appreciated.
Thank you!
You should not have View
s as properties of View
s. If it's a customisable part of a bigger view, store a closure that returns a view instead.
struct ProductsTabButton<ButtonView: View>: View {
@State var sheetActiveBool: Bool = false
var dismissFunction: () -> Void
var buttonColor: String
var buttonText: String
var buttonIcon: String
var buttonView: () -> ButtonView
// ...
}
You can pass this closure to sheet
directly:
.sheet(isPresented: $sheetActiveBool, onDismiss: dismissFunction, content: buttonView)
If you want a default value for this property, write an initialiser in an extension:
struct ProductsTabButton<ButtonView: View>: View {
// ...
init(buttonColor: String = "rmWhite", buttonText: String = "Button Text", buttonIcon: String = "list.dash", @ViewBuilder buttonView: @escaping () -> ButtonView, dismiss: @escaping () -> Void) {
self.buttonColor = buttonColor
self.buttonIcon = buttonIcon
self.dismissFunction = dismiss
self.buttonText = buttonText
self.buttonView = buttonView
}
// ...
}
extension ProductsTabButton where ButtonView == BackgroundView {
init(buttonColor: String = "rmWhite", buttonText: String = "Button Text", buttonIcon: String = "list.dash", dismiss: @escaping () -> Void) {
self.init(buttonColor: buttonColor, buttonText: buttonText, buttonIcon: buttonIcon, buttonView: { BackgroundView() }, dismiss: dismiss)
}
}