Home > Net >  How can I make a generic UIViewRepresentable struct?
How can I make a generic UIViewRepresentable struct?

Time:11-25

I want build a struct that it takes a UI type as input and it present that UI in SwiftUI, for example I have this down codes for UILabel and UIButton, I want make a generic one to free me from making an individual struct for each UI from UIKit:

struct UILabelViewRepresentable: UIViewRepresentable {
    
    let configuration: (UILabel) -> ()
    
    func makeUIView(context: Context) -> UILabel {
       return UILabel()
    }
    
    func updateUIView(_ uiView: UILabel, context: Context) {
        configuration(uiView)
    }
}



struct UIButtonViewRepresentable: UIViewRepresentable {
    
    let configuration: (UIButton) -> ()
    
    func makeUIView(context: Context) -> UIButton {
       return UIButton()
    }
    
    func updateUIView(_ uiView: UIButton, context: Context) {
        configuration(uiView)
    }
}

Here what I tried so far:

struct GenericUIViewRepresentable<UIViewType: UIView>: UIViewRepresentable {
    
    let uiViewType: UIViewType
    let configuration: (UIViewType) -> ()
    
    func makeUIView(context: Context) -> UIViewType {
        return uiViewType
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {
        configuration(uiView)
    }
}

it makes an error when I want use it:

Cannot convert value of type 'UILabel.Type' to expected argument type 'UIView'

So I know about the error, I want make my code works and it makes me free to type all UIKit UI that I want.

use case:

struct ContentView: View {
    
    var body: some View {
        
        GenericUIViewRepresentable(uiViewType: UILabel, configuration: { label in
            label.text = "Hello, World!"
        })

    }
    
}

CodePudding user response:

You want to pass in the UIView type, not just a UIView instance. This means you want to do UIViewType.Type rather than UIViewType.

Code:

struct GenericUIViewRepresentable<UIView: UIKit.UIView>: UIViewRepresentable {
    let uiViewType: UIView.Type
    let configuration: (UIView) -> ()

    func makeUIView(context: Context) -> UIView {
        uiViewType.init()
    }

    func updateUIView(_ uiView: UIView, context: Context) {
        configuration(uiView)
    }
}

Usage:

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello world!")

            GenericUIViewRepresentable(uiViewType: UILabel.self) { label in
                label.text = "Other text!"
            }
        }
    }
}

Here on swift.org is where you can learn more about metatype types.

  • Related