代码之家  ›  专栏  ›  技术社区  ›  Benjamin RD

将通用函数从Alamofire 3迁移到Alamofire 4

  •  1
  • Benjamin RD  · 技术社区  · 7 年前

    我正在用迁移此代码 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<[T]>)-&燃气轮机;()应为 参数类型“(DataResponse<\ugt;)-&燃气轮机;作废'

    我怎样才能修复它?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Sandeep    7 年前

    您正在从异步方法返回,并期望结果是有效的,我认为您应该重新考虑 sendRequest 方法一点。您可以将其设置为需要完成闭包。

    此外,您的BaseUser似乎不是一个模型类,而是一个处理程序类,可以这么说。它只有两个属性,它们是闭包,您试图从http请求映射什么。它应该有一些真正的属性。

    有了它,如果您有一个纯模型类和一个适当的send方法,您就可以很容易地实现您正在尝试的目标。

    您案例中的错误是因为您正在使用, AlamoFileObject映射器 并试图在不实际实现协议的情况下映射值。

    查看方法的签名,

    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 .如果您遵守协议 Mappable 从…起 ObjectMapper ,应该没问题。

    class BaseUser: BaseMappable {
    
        func mapping(map: Map) {
            // map your actual properties here
            // like username, name
        }
    }
    

    我也改变了你的想法 发送请求 方法,这样它不返回值,而是执行请求并在完成后执行回调。

    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 ,希望是类型, 可映射的

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

    这样你就可以走了。请注意,我向您展示了如何解决您遇到的问题。我还做了一些小的重构,只是为了让代码更清晰。

    请根据您的需要进行更改。