使用通用解码类型的网络呼叫

时间:2017-09-17 01:49:09

标签: ios swift generics nsurlsession foundation

我正在尝试创建一个通用的网络功能,我正在寻找一个API处理程序,它将从网络下载JSON并将主题转换为符合Decodable协议的Swift结构。目前我使用的是显式类型:

struct MyObject : Decodable {
    let id   : Int
    let name : String
}

static fileprivate func makeNetworkRequest(url: URL, completionHandler: @escaping(_ error: Error?, _ myObject: MyObject?) -> ()) {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        // handle error
        do {
            let myNewObject = try JSONDecoder().decode(MyObject.self, from: data!)
            completionHandler(nil, myNewObject)
        }
        catch let error {
            completionHandler(error, nil)
            return
        }
    }.resume()
}

我希望创建一个泛型函数,我可以指定任何确认到Decodable的数据类型,并在完成处理程序中返回数据对象。有点像:

static fileprivate func makeNetworkRequest<T>(url: URL, type: <<<Decodable Type>>>, completionHandler: @escaping(_ error: Error?, _ myObject: <<<Deocable Object>>>?) -> ()) {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        // handle error
        do {
            let myNewObject = try JSONDecoder().decode(<<<Decodable Type>>>.self, from: data!)
            completionHandler(nil, myNewObject)
        }
        catch let error {
            completionHandler(error, nil)
            return
        }
    }.resume()
}

但是,我似乎无法正确获取功能参数。我没有很多使用泛型的经验。任何帮助将不胜感激

1 个答案:

答案 0 :(得分:1)

您可以模仿decode的{​​{1}}方法声明:

JSONDecoder

将上面的模式应用于您的代码,定义应该是这样的:

open func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable

或者你可以这样写:

static fileprivate func makeNetworkRequest<T>(url: URL, type: T.Type, completionHandler: @escaping (_ error: Error?, _ myObject: T?) -> ())
where T: Decodable
{
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        // handle error
        do {
            let myNewObject = try JSONDecoder().decode(T.self, from: data!)
            completionHandler(nil, myNewObject)
        } catch let error {
            completionHandler(error, nil)
            return
        }
    }.resume()
}