Please take a look at my code:
struct Person: Codable {
var name: String
var age: Double
var birthday: Date
var selectedItem: Car
}
struct Car: Codable {
var companyName: String
var creationDate: Date
}
struct iPhone: Codable {
var model: String
var creationDate: Date
var isScreenBroken: Bool = true
}
struct Person: Codable { // "Type 'Person' does not conform to protocol 'Decodable'", "Type 'Person' does not conform to protocol 'Encodable'"
var name: String
var age: Double
var birthday: Date
var selectedItem: Codable // I've changed this line
}
struct Car: Codable {
var companyName: String
var creationDate: Date
}
struct iPhone: Codable {
var model: String
var creationDate: Date
var isScreenBroken: Bool = true
}
Type 'Person' does not conform to protocol 'Decodable'
Type 'Person' does not conform to protocol 'Encodable'
I don't understand why is this happening. It knows that selectedItem
is conforming to Encodable
& Decodable
:
var selectedItem: Codable
I'm new to protocols in Swift so please when answering try to explain what's happening here.
Thanks!
The problem for the compiler here is that normally when a type is defined to conform to Codable
then the compiler synthesises code for you to make Person
in this case conform to the protocol. It does this by creating an implementation of init(from decoder: Decoder) throws
and one of func encode(to encoder: Encoder) throws
for you.
But when you change selectedItem
to be of type Codable
then the compiler can no longer synthesise these methods since it needs to know exactly what properties the type of selectedItem
has to correctly generate the code.
What you need to do here is to use generics
struct Person<T: Codable>: Codable {
var name: String
var age: Double
var birthday: Date
var selectedItem: T
}
struct Car: Codable {
var companyName: String
var creationDate: Date
}
struct iPhone: Codable {
var model: String
var creationDate: Date
var isScreenBroken: Bool = true
}
Then the compiler is happy again and you can use it like
let person = Person(name: "Joe", age: 40, birthday: date, selectedItem: Car(companyName: "Ford", creationDate: Date()))