我正在尝试创建一个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中定义对象。
答案 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")