I'm trying to get data by encode model which conforms to Encodable
protocol. But it's failed to invoke func encode
like code below:
// MARK: - Demo2
class TestClass2: NSObject, Encodable {
var x = 1
var y = 2
}
var dataSource2: Encodable?
dataSource2 = TestClass2()
// error: `Cannot invoke 'encode' with an argument list of type '(Encodable)'`
let _ = try JSONEncoder().encode(dataSource2!)
//func encode<T>(_ value: T) throws -> Data where T : Encodable
But in another demo, it works well, why?
// MARK: - Demo1
protocol TestProtocol {
func test()
}
class TestClass1: NSObject, TestProtocol {
func test() {
print("1")
}
var x = 1
var y = 2
}
var dataSource1: TestProtocol?
dataSource1 = TestClass1()
func logItem(_ value: TestProtocol) {
value.test()
}
logItem(dataSource1!)
Try this code, which extend encodable
extension Encodable {
func toJSONData() -> Data? {
return try? JSONEncoder().encode(self)
}
}
Use
var dataSource2: Encodable?
dataSource2 = TestClass2()
let data = dataSource2?.toJSONData()
Your 2 examples are different.
JSONEncoder().encode() expects a concrete class which conforms to the procotol Encodable
. The reference dataSource2
holds a protocol and not a concrete class.
logItem
on the other hands, only takes a protocol as input, and NO concrete class which conforms to the protocol. This is the difference between your examples and why your second case is working and the first case does not.
With your current setup, it will not work. You need to pass in a concrete class to the JSONEncoder.
As long as TestClass2
is Encodable
you can use following code. encode
should know what to encode. It refers to class properties to do that. Encodable
itself doesn't contain any properties.
JSONEncoder().encode(dataSource2 as! TestClass2)