【问题标题】:Migrating generic function from Alamofire 3 to Alamofire 4将通用函数从 Alamofire 3 迁移到 Alamofire 4
【发布时间】:2018-04-05 21:38:41
【问题描述】:

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

我该如何解决?

【问题讨论】:

  • 你解决这个问题了吗?
  • @Nizzam 是的,使用本机实现也更容易阅读 Sandeep 答案
  • 为什么我的 alamofire 没有 responseObject ?

标签: ios swift alamofire


【解决方案1】:

您正在从异步方法返回,并期望结果有效,我认为您应该重新考虑您对sendRequest 方法的实现。你可以让它完成关闭。

另外,你的 BaseUser 似乎不是一个模型类,它更像是一些处理程序类,可以这么说。它只有两个闭包属性,你想从 http 请求映射什么。它应该有一些真实的属性。

有了这个,如果你有一个纯模型类和一个正确的发送方法,你可以很容易地实现你正在尝试的东西。

您的错误是因为您正在使用 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 类型。如果你符合ObjectMapperMappable协议,应该没问题。

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
    }
}

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 2023-03-14
    • 2023-04-01
    • 1970-01-01
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多