Afnetworking post 请求的代码提取
Code extraction on Afnetworking post request
我正在尝试提取一个 post 请求,以便它可以被重新使用并尽可能保持我的代码干燥,但我有点挣扎。我开始于:
func createAccount() {
let manager = AFHTTPSessionManager()
let dob = self.dobTextField.text!.components(separatedBy: "/")
let URL = "https://splitterstripeservertest.herokuapp.com/account"
let params = [
"first_name": firstNameTextField.text!.trim(),
"last_name": lastNameTextField.text!.trim(),
"line1": addressLine1TextField.text!.trim(),
"city": cityTextField.text!.trim(),
"postal_code": postCodeTextField.text!.trim(),
"email": emailTextField.text!.trim(),
"day": UInt(dob[0])! as UInt,
"month": UInt(dob[1])! as UInt,
"year": UInt(dob[2])! as UInt] as [String : Any]
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
do {
let response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as? [String: Any]
self.stripeAccountID = response?["id"] as! String
self.stopAnimating()
self.goToFinalStage()
} catch {
print("Serialising new account json object went wrong.")
self.stopAnimating()
}
}, failure: { (operation, error) -> Void in
self.handleError(error as NSError)
self.stopAnimating()
})
}
并归结为:
func createAccount() {
let request = HttpRequest()
let response = request.post(params: setParams(), URLExtension: "account")
if (response != nil) {
successfulRequest(response: response!)
} else {
failedRequest(response: response!)
}
}
func successfulRequest(response: AnyObject) {
self.stripeAccountID = response["id"] as! String
createMainBillSplitter()
self.stopAnimating()
performSegue(withIdentifier: "segueToFinalRegistrationViewController", sender: self)
}
func failedRequest(response: AnyObject) {
self.stopAnimating()
self.handleError(response["failed"] as! NSError)
}
其中 HTTPRequest 是:
class HttpRequest {
let manager = AFHTTPSessionManager()
let baseURL = "https://splitterstripeservertest.herokuapp.com/account"
func post(params: [String: Any], URLExtension: String) -> AnyObject? {
let URL = baseURL + URLExtension
var response = [String: Any]()
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
do {
response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as! [String: Any]
} catch {
print("Serialising new account json object went wrong.")
}
}, failure: { (operation, error) -> Void in
response = ["failed": error]
})
return response as AnyObject?
}
func handleError(_ error: NSError) -> UIAlertController {
let alert = UIAlertController(title: "Please Try Again", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
return alert
}
}
但是,我收到错误消息是因为响应为零,我确定这是因为没有完成处理程序。我只是不太了解如何在这种情况下实施它们,因此非常感谢朝着正确方向的推动。提前致谢!
您对同步与异步操作感到困惑。
manager.post 函数将创建您的 http 请求并调用 success 完成后关闭。但是由于该函数是作为异步操作实现的,因此您的代码不会在执行该 http 请求时停止。因此,您的代码将继续执行,在您的情况下,下一行是您 returning response基本上是你的空字符串数组。
func post(params: [String: Any], URLExtension: String) -> AnyObject? {
let URL = baseURL + URLExtension
var response = [String: Any]()
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
// this closure is executed only when the request is completed
do {
response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as! [String: Any]
} catch {
print("Serialising new account json object went wrong.")
}
}, failure: { (operation, error) -> Void in
response = ["failed": error]
})
return response as AnyObject? // <<-- this line is executed right after the manager.post line above, but the success closure was not called yet because the request is still going on.
}
因此,您需要做的不是 return 调用 manager.post 之后的响应,而是 return 从成功闭包内部响应。但是您不能简单地使用 return response 语句。您需要将 response 作为参数传递给您将传递给 [ 的回调闭包=59=]函数.
像这样:
func createAccount() {
let request = HttpRequest()
let response = request.post(params: setParams(),
URLExtension: "account",
success: {response in
// enter here the code to be executed when request is completed.
successfulRequest(response: response)
},
fail: {response in
failedRequest(response: response)
},)
}
而您的 class HttpRequest post 函数将是:
func post(params: [String: Any], URLExtension: String, success:([String: Any] -> Void), fail:([String: Any] -> Void)) -> AnyObject? {
let URL = baseURL + URLExtension
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
do {
response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as! [String: Any]
success(response)
} catch {
print("Serialising new account json object went wrong.")
}
}, failure: { (operation, error) -> Void in
response = ["failed": error]
fail(response)
})
}
PS:您的代码假设它始终能够解码 JSON 响应。尽管您正在使用 do / catch,但如果由于某种原因 JSON 解码失败,则不会将任何响应发送回您的调用函数。因此,该应用程序将被卡住。我建议您在 catch[=42 中调用 fail() 回调=]块。
我正在尝试提取一个 post 请求,以便它可以被重新使用并尽可能保持我的代码干燥,但我有点挣扎。我开始于:
func createAccount() {
let manager = AFHTTPSessionManager()
let dob = self.dobTextField.text!.components(separatedBy: "/")
let URL = "https://splitterstripeservertest.herokuapp.com/account"
let params = [
"first_name": firstNameTextField.text!.trim(),
"last_name": lastNameTextField.text!.trim(),
"line1": addressLine1TextField.text!.trim(),
"city": cityTextField.text!.trim(),
"postal_code": postCodeTextField.text!.trim(),
"email": emailTextField.text!.trim(),
"day": UInt(dob[0])! as UInt,
"month": UInt(dob[1])! as UInt,
"year": UInt(dob[2])! as UInt] as [String : Any]
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
do {
let response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as? [String: Any]
self.stripeAccountID = response?["id"] as! String
self.stopAnimating()
self.goToFinalStage()
} catch {
print("Serialising new account json object went wrong.")
self.stopAnimating()
}
}, failure: { (operation, error) -> Void in
self.handleError(error as NSError)
self.stopAnimating()
})
}
并归结为:
func createAccount() {
let request = HttpRequest()
let response = request.post(params: setParams(), URLExtension: "account")
if (response != nil) {
successfulRequest(response: response!)
} else {
failedRequest(response: response!)
}
}
func successfulRequest(response: AnyObject) {
self.stripeAccountID = response["id"] as! String
createMainBillSplitter()
self.stopAnimating()
performSegue(withIdentifier: "segueToFinalRegistrationViewController", sender: self)
}
func failedRequest(response: AnyObject) {
self.stopAnimating()
self.handleError(response["failed"] as! NSError)
}
其中 HTTPRequest 是:
class HttpRequest {
let manager = AFHTTPSessionManager()
let baseURL = "https://splitterstripeservertest.herokuapp.com/account"
func post(params: [String: Any], URLExtension: String) -> AnyObject? {
let URL = baseURL + URLExtension
var response = [String: Any]()
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
do {
response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as! [String: Any]
} catch {
print("Serialising new account json object went wrong.")
}
}, failure: { (operation, error) -> Void in
response = ["failed": error]
})
return response as AnyObject?
}
func handleError(_ error: NSError) -> UIAlertController {
let alert = UIAlertController(title: "Please Try Again", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
return alert
}
}
但是,我收到错误消息是因为响应为零,我确定这是因为没有完成处理程序。我只是不太了解如何在这种情况下实施它们,因此非常感谢朝着正确方向的推动。提前致谢!
您对同步与异步操作感到困惑。
manager.post 函数将创建您的 http 请求并调用 success 完成后关闭。但是由于该函数是作为异步操作实现的,因此您的代码不会在执行该 http 请求时停止。因此,您的代码将继续执行,在您的情况下,下一行是您 returning response基本上是你的空字符串数组。
func post(params: [String: Any], URLExtension: String) -> AnyObject? {
let URL = baseURL + URLExtension
var response = [String: Any]()
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
// this closure is executed only when the request is completed
do {
response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as! [String: Any]
} catch {
print("Serialising new account json object went wrong.")
}
}, failure: { (operation, error) -> Void in
response = ["failed": error]
})
return response as AnyObject? // <<-- this line is executed right after the manager.post line above, but the success closure was not called yet because the request is still going on.
}
因此,您需要做的不是 return 调用 manager.post 之后的响应,而是 return 从成功闭包内部响应。但是您不能简单地使用 return response 语句。您需要将 response 作为参数传递给您将传递给 [ 的回调闭包=59=]函数.
像这样:
func createAccount() {
let request = HttpRequest()
let response = request.post(params: setParams(),
URLExtension: "account",
success: {response in
// enter here the code to be executed when request is completed.
successfulRequest(response: response)
},
fail: {response in
failedRequest(response: response)
},)
}
而您的 class HttpRequest post 函数将是:
func post(params: [String: Any], URLExtension: String, success:([String: Any] -> Void), fail:([String: Any] -> Void)) -> AnyObject? {
let URL = baseURL + URLExtension
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
do {
response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as! [String: Any]
success(response)
} catch {
print("Serialising new account json object went wrong.")
}
}, failure: { (operation, error) -> Void in
response = ["failed": error]
fail(response)
})
}
PS:您的代码假设它始终能够解码 JSON 响应。尽管您正在使用 do / catch,但如果由于某种原因 JSON 解码失败,则不会将任何响应发送回您的调用函数。因此,该应用程序将被卡住。我建议您在 catch[=42 中调用 fail() 回调=]块。