我正在尝试构建一个名为makePostBuilder
的实用函数,它看起来像这样。
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
}
此函数的返回类型显然不正确。我希望它返回一个URLRequest
实例或一个Error
实例。错误实例主要是因为可选的解包操作可以返回有价值的消息,而不仅仅是返回nil
(根据当前实现。
我一直在思考typealias
的思路,但是我不确定这是否是正确的方法。
//not sure if this is right
typealias CustomRequestType = (URLRequest, Error)
在适当的类型定义的最后,我希望函数看起来像这样
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
}
我想我已经接近了,但还没到那儿。如果社区可以为我提供一些文档,我也很喜欢!
更新:可能的解决方案?
//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)
}
答案 0 :(得分:3)
有一个内置enum Result
可以用作返回类型。并且在无法创建URLError(code: .badURL)
的情况下,可以使用URL
(由Foundation提供)。因此:
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)
}
编写此函数的自然方法是声明它throws
,如下所示:
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
}
然后让呼叫者使用do/catch
来处理错误,而不是让呼叫者切换Result
情况。
如果呼叫者确实希望使用Result
,则可以使用Result(catching:)
初始化程序,该初始化程序(带有结尾闭包语法)如下所示:
let requestResult = Result { try makePostRequest(apiUrl: urlString, params: [:]) }