I'm trying to build a utility function called makePostBuilder
which looks something like this.
fileprivate func makePostRequest(apiUrl: String, params: [String: String]) -> URLRequest? {
// build url
let urlString = "\(apiUrl)"
guard let serviceUrl = URL(string: urlString) else { return nil }
// build url request
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
//set http body for url request with incoming params
guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: []) else {
return nil
}
request.httpBody = httpBody
return request
}
The return type of this function is obviously incorrect. I would like it to either return a URLRequest
instance OR an Error
instance. The error instance is mainly so the optional unwrapping can return a valuable message instead of just nil
(as per the current implementation.
I was thinking along the lines of a typealias
, but I am not sure if that is the right approach.
//not sure if this is right
typealias CustomRequestType = (URLRequest, Error)
At the end of the appropriate type definitions, I would like the function to look something like this
fileprivate func makePostRequest(apiUrl: String, params: [String:String]) -> CustomType {
let urlString = apiUrl
guard let serviceUrl = URL(string: urlString) else { return //error based on customtype? }
// build url request
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
//set http body for url request with incoming params
guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: []) else {
return //error type
}
//return success type
request.httpBody = httpBody
return request
}
I think I'm getting close, but not quite there yet. I'd also love if the community could point me to some docs!
UPDATE: Possible Solution?
//does this seem plausible?
enum DCError: String, Error {
case invalidUrl = "the url seems to be invalid"
}
typealias DCUrlRequestType = Result<URLRequest, Error>
fileprivate func makePostRequest(apiUrl: String, params: Dictionary<String, String>) -> DCUrlRequestType {
let urlString = apiUrl
guard let serviceUrl = URL(string: urlString) else {
return DCUrlRequestType.failure(DCError.invalidUrl)
}
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
return DCUrlRequestType.success(request)
}
There is a built-in enum Result
you can use as your return type. And you can use URLError(code: .badURL)
(provided by Foundation) in the case where you can't create the URL
. Thus:
fileprivate func makePostRequest(apiUrl: String, params: [String: String]) -> Result<URLRequest, Error> {
let urlString = "\(apiUrl)"
guard let serviceUrl = URL(string: urlString) else {
return .failure(URLError(.badURL))
}
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: params, options: [])
} catch {
return .failure(error)
}
return .success(request)
}
The natural way to write this function is to declare that it throws
, like this:
fileprivate func makePostRequest(apiUrl: String, params: [String: String]) throws -> URLRequest? {
let urlString = "\(apiUrl)"
guard let serviceUrl = URL(string: urlString) else {
throw URLError(.badURL)
}
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONSerialization.data(withJSONObject: params, options: [])
return request
}
and then let the caller use do/catch
if she wants to handle the error, instead of making the caller switch over the Result
cases.
If the caller really wants a Result
, she can use the Result(catching:)
initializer, which (with trailing closure syntax) looks like this:
let requestResult = Result { try makePostRequest(apiUrl: urlString, params: [:]) }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.