Reputation: 236
I am trying to create a createRequest function that I can re-use for all my networking calls, some require posting JSON and other don't so I was thinking of creating a function that takes an optional generic object; something in theory like this:
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
}
I would like to return the URLRequest with the option of passing different JSON objects this function. I read that you cant do it this way unless you define the type on the return function but I can't define my object in the return.
Upvotes: 0
Views: 278
Reputation: 63157
Preface: This code's a mess of inconsistent indentation and unnecessary whitespace (it reads like a double-spaced essay lol), I cleaned it up.
Looks like your function needs to take a T
, but not just any T
, but one that is constrained to being Encodable
. This is a common observation: more general generic parameters are compatible with more types, but can do we less with them. By containing T
to Encodable
, we can use it with JSONEncoder.encode
.
The label withData:
is a misnomer, because that parameter won't have type Data
. Something like withBody:
would work better.
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")
Upvotes: 1