我正在将此代码与 Alamofire 3
迁移到 Alamofire 4
。
引用是:Creating a generic method with AlamoFire in Swift
我有这门课:
import Foundation
import Alamofire
import AlamofireObjectMapper
import ObjectMapper
class HttpHandler {
static func sendRequest<T:BaseUser>(url: String, parameters: [String: AnyObject]?) -> T {
let res : T
Alamofire.request(url)
.validate()
.responseObject { (response: DataResponse<[T]>) in
switch response.result {
case .Success(let value):
res.valueHandle?(value)
case .Failure(let error):
res.errorHandle?(error)
}
}
return res
}
}
class BaseUser: ResponseObjectSerializable {
var valueHandle : ((BaseUser)->())?
var errorHandle : ((NSError)->())?
required init?(response: HTTPURLResponse, representation: AnyObject) {
}
}
public protocol ResponseObjectSerializable {
init?(response: HTTPURLResponse, representation: AnyObject)
}
但是,我收到了这个错误:
Cannot convert value of type '(DataResponse<[T]>) -> ()' to expected argument type '(DataResponse<_>) -> Void'
我该如何解决?
最佳答案
您正在从异步方法返回,并且期望结果有效,我认为您应该重新考虑一下您对 sendRequest
方法的实现。你可以让它完成关闭。
此外,您的 BaseUser 似乎不是模型类,它更像是一些处理程序类,可以这么说。它只有两个闭包属性,你想从 http 请求映射什么。它应该有一些真正的属性。
有了它,如果您有一个纯模型类和一个适当的发送方法,您就可以很容易地实现您正在尝试的目标。
您的案例中的错误是因为您正在使用 AlamofireObjectMapper 并尝试在没有实际实现协议(protocol)的情况下映射值。
查看方法的签名,
public func responseObject<T>(queue: DispatchQueue? = default,
keyPath: String? = default,
mapToObject object: T? = default,
context: MapContext? = default,
completionHandler: @escaping(Alamofire.DataResponse<T>) -> Swift.Void) -> Self where T : BaseMappable
此处的通用参数T
应为BaseMapper
类型。如果您符合 ObjectMapper 的协议(protocol) Mappable
,应该没问题。
class BaseUser: BaseMappable {
func mapping(map: Map) {
// map your actual properties here
// like username, name
}
}
我还稍微更改了您的 sendRequest
方法,这样它就不会返回值,而是执行请求并在完成后执行回调。
static func sendRequest<T:BaseUser>(url: String,
parameters: [String: AnyObject]?,
completion: @escaping ([T], Error?) -> Void) {
Alamofire.request(url)
.validate()
.responseObject { (response: DataResponse<[T]>) in
switch response.result {
case .success(let value):
completion(value, nil)
case .failure(let error):
completion([], error)
}
}
}
代码看起来不错,但还不能运行。您期望将您的响应映射到 BaseUser
数组,但是 AlamofireObjectMapper
期望它的类型为 Mappable
。
现在你可以对数组使用扩展并遵守协议(protocol)。我们可以使用 Swift 4.1 Conditional Conformance 在这里。
extension Array: BaseMappable where Element: BaseMappable {
public mutating func mapping(map: Map) {
var userHolder: [BaseUser] = []
// map array of values to your BaseUser
}
}
有了这个你就可以开始了。请注意,我向您展示了如何解决您遇到的问题。我还做了一些小的重构,只是为了让代码更清晰。
请根据您的需要进行更改。
关于ios - 将通用函数从 Alamofire 3 迁移到 Alamofire 4,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49681933/