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

标签 ios swift alamofire

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

相关文章:

ios - 代码 : Request to open App failed

ios - 如何在 Swift 中本地化 tableView 单元格?

ios - Swift 4 - 使用哪种类型的数组 - 将 JSON 响应解析为数组

ios - UINavigationController:确定后退按钮是否被按下或 popViewController 动画

ios - 如何将值附加到模型类

swift - 如何在 swiftyJSON 和 Alamofire 中获取字典的随机值

ios - 保存和读取登录到钥匙串(keychain)不工作 IOS swift

ios - iOS中pod install命令的工作流程

ios - 使用 Swift 在 Ios 中本地导入数据表并将其用于搜索功能

ios - UISearchController:searchResultsController 不显示