Swift通用URLRequest

时间:2019-05-07 02:15:03

标签: swift

我正在尝试创建一个createRequest函数,我可以将其重新用于所有的网络调用,有些函数要求发布JSON,而另一些函数则不需要,因此我在考虑创建一个带有可选通用对象的函数。理论上是这样的:

struct Person: Codable {

var fName: String
var lName: String

}

struct Location: Codable {

 var city: String
 var state: String

}

let data = Person(fName: "John", lName: "Smith")
let location = Location(city: "Atlanta", state: "Georgia")

createRequest(withData: data)
createRequest(withData: location)

 private func createRequest(withData:T) throws -> URLRequest { 

        var newRequest = URLRequest(url: URL(string: "\(withUrl)")!)

        newRequest.httpMethod = method.rawValue

       if let data = withData {

            newRequest.setBody = data

         }

        if withAPIKey {

            newRequest.setValue(apiKey, forHTTPHeaderField: "APIKEY")

        }

        return newRequest

    }

我想返回URLRequest,并带有通过此函数传递不同JSON对象的选项。我读到,除非您在return函数上定义类型,否则您不能这样做,但是我无法在return中定义对象。

1 个答案:

答案 0 :(得分:1)

前言:这段代码杂乱的缩进和不必要的空格(读起来像是双倍行距的论文大声笑),我将其清理干净。

看起来您的函数需要采用T,但不仅需要T,还需要约束为Encodable。这是一个常见的观察:更通用的泛型参数与更多类型兼容,但对于它们而言,我们做的可能更少。通过将T包含到Encodable中,我们可以将其与JSONEncoder.encode一起使用。

标签withData:的使用不当,因为该参数的类型为Data。像withBody:这样的东西会更好。

import Foundation

struct Person: Codable {
    var fName: String
    var lName: String
}

struct Location: Codable {
    var city: String
    var state: String
}

// stubs for making compilation succeed
let apiKey = "dummy"
let withAPIKey = true
enum HTTPMethod: String { case GET } 

private func createRequest<Body: Encodable>(method: HTTPMethod, url: URL, withBody body: Body) throws -> URLRequest { 

    var newRequest = URLRequest(url: url)
    newRequest.httpMethod = method.rawValue

    newRequest.httpBody = try JSONEncoder().encode(body)

    if withAPIKey {
        newRequest.setValue(apiKey, forHTTPHeaderField: "APIKEY")
    }

    return newRequest
}

let data = Person(fName: "John", lName: "Smith")
let location = Location(city: "Atlanta", state: "Georgia")