I am wrapping Core Data objects into structs to make them Codable.
[NB: Before your direct me to writing the swift file for each Core Data class, I would like to say that wrapping the NSManagedObject children result from a conscious choice in favour of code maintainability, as the data model may evolve in the future.]
I have the few classes like these, here is an example:
struct CodableNeed : Codable {
enum CodingKeys: String, CodingKey {
...
}
var need:Need
init (_ need:Need) {
self.need = need
}
init(from decoder: Decoder) throws {
....
}
func encode(to encoder: Encoder) throws {
....
}
}
This works actually pretty well, as any update in the init(from:decoder) of the struct is actually stored in the ManagedObjectContext.
In order to let each NSManagedObject class instance return their own struct, I defined a protocol where each class instance may return their own Codable struct:
protocol CodableWhenWrapped {
func wrapToCodable() -> Codable
}
extension Need : CodableWhenWrapped {
func wrapToCodable() -> Codable {
return CodableNeed(self)
}
}
I then use this in an encoding function:
func jsonDataOfCodable<T:Encodable>(_ object:T) throws -> Data {
let encoder = JSONEncoder()
let data = try encoder.encode(object)
return data
}
and I call this function to generate an URLSessionUploadTask :
func updateTaskFor<T: NSManagedObject> (_ object:T, withSession session:URLSession) throws -> URLSessionUploadTask
where T: CodableWhenWrapped
{
let encoder = JSONEncoder()
// Here is the compile error:
// " Cannot invoke 'jsonDataOfCodable' with an argument list of type '(Codable)' "
let jsonData = try jsonDataOfCodable(object.wrapToCodable())
// then continue with generating the uploadTask
let url = "https://myurl.com/"
let request = URLRequest(url: url)
let updateTask = session.uploadTask(with: request, from: jsonData) { (data, response, error) in
....
}
}
Here is the issue: the code does not compile when calling jsonDataOfCodable : Cannot invoke 'jsonDataOfCodable' with an argument list of type '(Codable)'.
Any idea why the compiler does not like this?
Note that I have the same issue when I specify <T:Codable>instead of <T:Encodable> in the jsonDataOfCodable prototype.
JSONEncoder().encoderequires a concrete type conforming to(En)codable, not the protocolCodableitself. You could use anassociatedtype. It might be easier to implementinit(from decoder:andencode(to encoder:in eachNSManagedObjectsublcass. Especially if there are relationships it's the only choice. - vadian