Swift 方法重载推理不起作用
Swift method overloading inference not working
我正在尝试为我的应用程序创建通用 JSON 映射器。我正在使用 Codable 协议,我有两个功能:一个将数据转换为可解码的,一个将可编码的转换为数据。这是我的实现:
struct JSONMapper: JSONMapperProtocol {
func map<T: Encodable>(from entity: T) -> Data? {
let encoder = JSONEncoder()
guard let data = try? encoder.encode(entity) else {
return nil
}
return data
}
func map<T: Decodable>(from data: Data) -> T? {
let decoder = JSONDecoder()
guard let entity = try? decoder.decode(T.self, from: data) else {
return nil
}
return entity
}
}
我对这些函数的理想用法是:
if let body = requestData.body {
request.httpBody = self.mapper.map(from: body)
}
requestData 是这个协议的一个实现:
protocol RequestData {
var method: HTTPMethod { get }
var host: String { get }
var path: String { get }
var header: [String: String]? { get }
var queryParameters: [String: String]? { get }
var body: Encodable? { get }
}
但是编译器给我以下错误:
Cannot convert value of type 'Encodable' to expected argument type 'Data'
我不明白为什么会这样,因为 'httpBody' 是一个数据而 'body' 是一个可编码的。编译器难道不能推断出这个吗?
感谢任何解决此问题的想法。
配置:
编译器:Swift4.2
Xcode: 10.1
解码见下文,编码只需将 JSONDecoder() 更改为 JSONEncoder()
let decoder = JSONDecoder()
if let data = response.data {
do {
let userList = try decoder.decode(UserList.self, from: data)
}
catch {
print(error)
}
}
使用它来解码响应数据,您可以使用结构或 class 然后使用 Codable 作为类型。
struct UserList: Codable {
var responseCode: String
var response: UserListResponse
}
可以像上面那样有多层可编码类型。
您的方法需要具体类型 (T
),它实现协议 Encodable
(<T: Encodable>
)。
所以你不能这样使用它,因为 body
必须是一个具体的类型,因为 Encodable
只是应该实现它的 struct/class 的协议。您必须指定实现此协议的类型。
要实现这一点,您可以声明 associatedtype
必须实现 Encodable
协议,然后您可以指定 body
的类型作为此关联类型
protocol RequestData {
...
associatedtype T: Encodable
var body: T? { get }
}
然后在实现协议的 struct/class 内部,您必须将 T
的类型指定为实现协议 Encodable
的具体类型 struct/class ]
struct SomeStruct: RequestData {
...
typealias T = SomeOtherStruct
var body: T?
}
然后编译器不会给你任何错误,它应该可以工作:
request.httpBody = self.mapper.map(from: body)
我正在尝试为我的应用程序创建通用 JSON 映射器。我正在使用 Codable 协议,我有两个功能:一个将数据转换为可解码的,一个将可编码的转换为数据。这是我的实现:
struct JSONMapper: JSONMapperProtocol {
func map<T: Encodable>(from entity: T) -> Data? {
let encoder = JSONEncoder()
guard let data = try? encoder.encode(entity) else {
return nil
}
return data
}
func map<T: Decodable>(from data: Data) -> T? {
let decoder = JSONDecoder()
guard let entity = try? decoder.decode(T.self, from: data) else {
return nil
}
return entity
}
}
我对这些函数的理想用法是:
if let body = requestData.body {
request.httpBody = self.mapper.map(from: body)
}
requestData 是这个协议的一个实现:
protocol RequestData {
var method: HTTPMethod { get }
var host: String { get }
var path: String { get }
var header: [String: String]? { get }
var queryParameters: [String: String]? { get }
var body: Encodable? { get }
}
但是编译器给我以下错误:
Cannot convert value of type 'Encodable' to expected argument type 'Data'
我不明白为什么会这样,因为 'httpBody' 是一个数据而 'body' 是一个可编码的。编译器难道不能推断出这个吗?
感谢任何解决此问题的想法。
配置:
编译器:Swift4.2
Xcode: 10.1
解码见下文,编码只需将 JSONDecoder() 更改为 JSONEncoder()
let decoder = JSONDecoder()
if let data = response.data {
do {
let userList = try decoder.decode(UserList.self, from: data)
}
catch {
print(error)
}
}
使用它来解码响应数据,您可以使用结构或 class 然后使用 Codable 作为类型。
struct UserList: Codable {
var responseCode: String
var response: UserListResponse
}
可以像上面那样有多层可编码类型。
您的方法需要具体类型 (T
),它实现协议 Encodable
(<T: Encodable>
)。
所以你不能这样使用它,因为 body
必须是一个具体的类型,因为 Encodable
只是应该实现它的 struct/class 的协议。您必须指定实现此协议的类型。
要实现这一点,您可以声明 associatedtype
必须实现 Encodable
协议,然后您可以指定 body
的类型作为此关联类型
protocol RequestData {
...
associatedtype T: Encodable
var body: T? { get }
}
然后在实现协议的 struct/class 内部,您必须将 T
的类型指定为实现协议 Encodable
struct SomeStruct: RequestData {
...
typealias T = SomeOtherStruct
var body: T?
}
然后编译器不会给你任何错误,它应该可以工作:
request.httpBody = self.mapper.map(from: body)