Search code examples
iosswiftswiftui

SwiftUI UIViewRepresentable: @Environment conforming to protocol?


I have the following code:

protocol CarItem: AnyObject, Observable {
    var carName:String { get }
}


struct CarViewUIKRepresented: UIViewRepresentable {
    
    @Environment(CarItem.self) var item // <<<<< ERROR: No exact matches in call to initializer 
    
    func makeUIView(context: Context) -> CarUIView {
        let carView = CarUIView()
        carView.setupWith(car:item)
        return carView
    }
    
    func updateUIView(_ uiView: CarUIView, context: Context) {
        
    }
    
}

class CarUIView : UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupWith<T:CarItem>(car:T) {
        ///
    }
    
}

I would like to be able to pass in the environment a model that conforms to the CarItem protocol. I am not sure if that is possible and if so how to accomplish that.

Is there a way to pass in the environment a model that adopts protocol CarItem and use it in UIViewRepresentable as a generic?


Solution

  • You need to use a generic on CarViewUIKRepresented :

    struct CarViewUIKRepresented<T: CarItem>: UIViewRepresentable {
        
        @Environment(T.self) var item
        
        func makeUIView(context: Context) -> CarUIView {
            let carView = CarUIView()
            carView.setupWith(car:item)
            return carView
        }
        
        func updateUIView(_ uiView: CarUIView, context: Context) {
            
        }
        
    }