Concrete type with protocols

Hey, Im trying to create generic data source for collection view that needs a model for every section of a collection view.
I need to be able to have multiple type of models, so means that I need to hold on to an array of rows.
But Im getting an error here, because I don't have a concrete type, is there any way I can achieve this?

protocol RowControllerType {
    associatedtype Model
    func update(to model: Model)
}

open class RowController: RowControllerType {
    typealias Model = Any
    func update(to model: Model) {}
}

open class GenericRowController<Model>: RowControllerType {
    func update(to model: Model) {}
}

class RowControllersManager: NSObject {
    var rowControllers: [RowController] = []
}

let row1 = RowController()
row1.update(to: "hey")

let row2 = GenericRowController<UIColor>()
row2.update(to: .red)

let manager = RowControllersManager()
manager.rowControllers.append(row1)
manager.rowControllers.append(row2)

Im getting Cannot convert value of type 'GenericRowController<UIColor>' to expected argument type 'RowController'

The issue is that rowControllers is defined as [RowController], but row2 is a GenericRowController<UIColor>, which is not a subtype of RowController. Ideally you would do this as defining rowControllers: [RowControllerType], but unfortunately without existentials this cannot be done.

Since you have RowController which is based on Any though, I suppose that you don't need the type information at that point. In that case you can try converting your GenericRowController to a RowController and appending the converted value instead?

2 Likes