protocol BackgroundContent: View{
}
struct BlueDivider: BackgroundContent {
var body: some View {
Divider()
.frame(minHeight: 1)
.background(.blue)
}
}
struct RedDivider: BackgroundContent {
var body: some View {
Divider()
.frame(minHeight: 1)
.background(.red)
}
}
var p: BackgroundContent = BlueDivider()
// Use of protocol 'BackgroundContent' as a type must be written 'any BackgroundContent'
p = RedDivider()
This always ask me to use
var p: any BackgroundContent = BlueDivider()
Is there any way to use generic type which accept any kind view?
Actually, I want to use view as a state like @State private var bgView: BackgroundContent = BlueDivider()
which i want to change at runtime like bgView = RedDivider()
I have made my custome view to place some other view at runtime by using this state.
CodePudding user response:
For your specific problem you can do something like this here:
struct SwiftUIView: View {
@State var isRed = false
var body: some View {
Devider()
.frame(height: 1)
.background(isRed ? Color.red : Color.blue)
}
}
CodePudding user response:
It is complicated but i have found a solution of this problem. First thing i have done with ObservableObject. Here is my example.
protocol BaseBackgroundContent {
var color: Color { get set }
}
class BlueContent: BaseBackgroundContent {
var color: Color = .blue
}
class RedContent: BaseBackgroundContent {
var color: Color = .red
}
And i created a custom view for Divider in this case.
struct CustomDivider: View {
var backgroundContent: any BaseBackgroundContent
var body: some View {
Divider()
.background(backgroundContent.color)
}
}
And now i used a viewModel which can be observable, and the protocol has to be Published.
class ExampleViewModel: ObservableObject {
@Published var backgroundContent: any BaseBackgroundContent = RedContent()
func change() {
backgroundContent = BlueContent()
}
}
Final step is the view. This is a exampleView. If you click the button you will see the BlueContent which was RedContent
struct Example: View {
@ObservedObject var viewModel = ExampleViewModel()
init() {
}
var body: some View {
VStack {
Text("Test")
CustomDivider(backgroundContent: viewModel.backgroundContent)
Button("Change") {
viewModel.change()
}
}
}
}