How to conform protocol to Identifiable

The problem is not that you can’t access the id as a concrete type (String?): e.g. try:

let firstID/*: String?*/ = models[0].id 

The problem here is that the ForEach initializer expects of a collection of an Identifiable-conforming type, but models is an array of any Model. This “any” (“existential”) type, as other “any” types, can’t conform to other protocols. Thus, any Model cannot conform to Identifiable. What you can do instead is create a wrapper type yourself which can conform to Identifiable:

struct AnyModel: Model {
  private var _model: any Model

  init(_ model: some Model) {
    _model = model // Automatically casts to “any” type
  }

  var id: String? {
    get { _model.id }
    set { _model.id = newValue }
  }
}

Then, you can use this wrapper type where you’d use the any type. E.g. models would now have a type [AnyModel]. This is a common strategy in Swift (see AnyHashable) and SwiftUI (see AnyView).

2 Likes