I’m reaching out today because I’m having an issue with SwiftData, and I’m on the verge of despair :).
I’m new to SwiftData, and there’s one thing that’s driving me crazy.
I want to save an array that contains several objects conforming to a protocol “Car”, but I’m getting the following error: Type ‘any Car’ cannot conform to ‘PersistentModel’. Here is the complete code:
import Foundation
import SwiftData
protocol Car: Identifiable, Codable, Hashable {
var id: UUID { get }
var modelName: String { get}
var price: Int { get }
}
@Model
class CarSeller: Identifiable {
var id: UUID
var cars: [any Car]
init(id: UUID, cars: [any Car]) {
self.id = id
self.cars = cars
}
convenience init() {
self.init(id: UUID(), cars: [])
}
}
@Model
class Audi: Car {
var id: UUID
var price: Int
var modelName: String
init(price: Int, id: UUID, modelName: String) {
self.price = price
self.id = id
self.modelName = modelName
}
enum CodingKeys: CodingKey {
case id, modelName, price
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
modelName = try container.decode(String.self, forKey: .modelName)
price = try container.decode(Int.self, forKey: .price)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(modelName, forKey: .modelName)
try container.encode(price, forKey: .price)
}
}
@Model
class Mercedes: Car {
var id: UUID
var price: Int
var modelName: String
init(price: Int, id: UUID, modelName: String) {
self.price = price
self.id = id
self.modelName = modelName
}
enum CodingKeys: CodingKey {
case id, modelName, price
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
modelName = try container.decode(String.self, forKey: .modelName)
price = try container.decode(Int.self, forKey: .price)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(modelName, forKey: .modelName)
try container.encode(price, forKey: .price)
}
}
@Model
final class Peugeot: Car {
var id: UUID
var modelName: String
var price: Int
init(price: Int, id: UUID, modelName: String) {
self.price = price
self.id = id
self.modelName = modelName
}
enum CodingKeys: CodingKey {
case id, modelName, price
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
modelName = try container.decode(String.self, forKey: .modelName)
price = try container.decode(Int.self, forKey: .price)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(modelName, forKey: .modelName)
try container.encode(price, forKey: .price)
}
}
I want to specify that the error appears on this line: var cars: [any Car]
In fact, I found a workaround solution by using an enum, but I didn’t find this solution very elegant.
Samir Mestari is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.