我正在将此代码与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)
}

但是,我收到此错误:

无法将类型'(DataResponse )->()'的值转换为预期值
参数类型'(DataResponse )->无效'

我该如何解决?

最佳答案

您正在从异步方法返回,并期望结果有效,我认为您应该重新考虑sendRequest方法的实现。您可以使其完成填充。

而且,您的BaseUser似乎不是模型类,而是某种处理程序类。它只有两个属性,即闭包,您尝试从http请求映射什么。它应该具有一些真实属性。

这样,如果您有一个纯模型类和一个适当的send方法,则可以轻松实现您尝试的目标。

您遇到的错误是因为您使用的是 AlamofireObjectMapper ,并且尝试在未实际实现协议的情况下映射值。

看一下方法的签名,

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 的协议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

现在,您可以使用扩展来排列并遵守协议。我们可以在这里使用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/

10-12 14:43