Home > Back-end >  SwiftUI polymorphic behaviour not working for View
SwiftUI polymorphic behaviour not working for View

Time:11-25

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()
            }
        }
    }
}
  • Related