我正在尝试创建一个post方法,以便我可以在代码中进一步重用它 我看到这个例子Returning data from async call in Swift function给出了我的问题的部分解决方案,但是一旦定义它就不知道如何调用该函数。
这是我试图调用的功能:
class func postRequest(url: URL, request: URLRequest, saveCookie: Bool, completionHandler: @escaping (_ postRequestStatus: [String:Any]) -> ()) {
let session = URLSession.shared
//So now no need of type conversion
let task = session.dataTask(with: request) {
(data, response, error) in
func displayError(_ error: String) {
print(error)
}
/* GUARD: Was there an error? */
guard (error == nil) else {
displayError("There was an error with your request: \(String(describing: error))")
return
}
guard let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 else {
displayError("Your request returned a status code other than 2xx!")
return
}
/* GUARD: Was there any data returned? */
guard let data = data else {
displayError("No data was returned by the request!")
return
}
/* Since the incoming cookies will be stored in one of the header fields in the HTTP Response,parse through the header fields to find the cookie field and save the data */
if saveCookie{
let httpResponse: HTTPURLResponse = response as! HTTPURLResponse
let cookies = HTTPCookie.cookies(withResponseHeaderFields: httpResponse.allHeaderFields as! [String : String], for: (response?.url!)!)
HTTPCookieStorage.shared.setCookies(cookies as [AnyObject] as! [HTTPCookie], for: response?.url!, mainDocumentURL: nil)
}
let json: [String:Any]?
do
{
json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String:Any] ?? [:]
}
catch
{
displayError("Could not parse the data as JSON: '\(data)'")
return
}
guard let server_response = json else
{
displayError("Could not parse the data as JSON: '\(data)'")
return
}
if let userID = server_response["UserID"] as? Int64 {
print(userID)
completionHandler(server_response)
}else{
displayError("Username or password incorrect.")
}
}
return task.resume()
}
这是来电者功能:
class func loginPostRequest(post_data: [String:Any], completionHandler: @escaping (_ postRequestStatus: [String:Any]) -> ()){
let url = URL(string: HTTPConstant.Login.Url)!
var request = URLRequest(url: url)
request.httpMethod = "POST"
var paramString = ""
for (key, value) in post_data
{
paramString = paramString + (key) + "=" + (value as! String) + "&"
}
request.httpBody = paramString.data(using: .utf8)
//in the line below I get the error message, extra argument "request" in call.
postRequest(url: url, request: request, saveCookie: true, completionHandler: { postRequestStatus in
completionHandler(postRequestStatus)
})
}
答案 0 :(得分:1)
你无法让loginPostRequest
返回NSDictionary
,因为你正在进行异步调用,你需要的是创建完成块,就像你使用postRequest
方法创建完成块一样,你也需要使用Swift 3要将URLRequest
与可变var
对象而不是NSMutableURLRequest
一起使用,您还需要将postRequest
函数的请求参数类型更改为URLRequest
,因此后者无需转换{ {1}}到NSMutableURLRequest
并使用Swift类型字典而不是URLRequest
NSDictionary
现在只需在方法class func loginPostRequest(post_data: [String:Any], completionHandler: @escaping (_ postRequestStatus: [String:Any]) -> ()){
let url = URL(string: HTTPConstant.Login.Url)!
var request = URLRequest(url: url)
request.httpMethod = "POST"
var paramString = ""
for (key, value) in post_data
{
paramString = paramString + (key as! String) + "=" + (value as! String) + "&"
}
request.httpBody = paramString.data(using: .utf8)
postRequest(url: url, request: request, saveCookie: true, completionHandler: { postRequestStatus in
completionHandler(postRequestStatus)
})
}
URLRequest
的请求的参数类型更改为NSMutableURLRequest
postRequest
现在,当你调用此class func postRequest(url: URL, request: URLRequest, saveCookie: Bool, completionHandler: @escaping (_ postRequestStatus: [String:Any]) -> ()) {
let session = URLSession.shared
//So now no need of type conversion
let task = session.dataTask(with: request) { (data, response, error) in
func displayError(_ error: String) {
print(error)
}
/* GUARD: Was there an error? */
guard (error == nil) else {
displayError("There was an error with your request: \(String(describing: error))")
return
}
guard let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 else {
displayError("Your request returned a status code other than 2xx!")
return
}
/* GUARD: Was there any data returned? */
guard let data = data else {
displayError("No data was returned by the request!")
return
}
/* Since the incoming cookies will be stored in one of the header fields in the HTTP Response,parse through the header fields to find the cookie field and save the data */
if saveCookie{
let httpResponse: HTTPURLResponse = response as! HTTPURLResponse
let cookies = HTTPCookie.cookies(withResponseHeaderFields: httpResponse.allHeaderFields as! [String : String], for: (response?.url!)!)
HTTPCookieStorage.shared.setCookies(cookies as [AnyObject] as! [HTTPCookie], for: response?.url!, mainDocumentURL: nil)
}
let json: [String:Any]?
do
{
json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String:Any] ?? [:]
}
catch
{
displayError("Could not parse the data as JSON: '\(data)'")
return
}
guard let server_response = json else
{
displayError("Could not parse the data as JSON: '\(data)'")
return
}
if let userID = server_response["UserID"] as? Int64 {
print(userID)
completionHandler(server_response)
}else{
displayError("Username or password incorrect.")
}
}
return task.resume()
}
时,你正在完成它的响应。
答案 1 :(得分:1)
接收闭包作为参数的函数可以像任何其他函数一样调用:
loginPostRequest
如果闭包是最后一个参数,你可以将它传递到括号外:
postRequest(url: yourUrlObject, request: yourUrlRequest, saveCookie: true/false, completionHandler: { postRequestStatus in
// ... code that will run once the request is done
})
您可以查看Swift手册,详细了解closures和functions。
顺便说一句,你的postRequest(url: yourUrlObject, request: yourUrlRequest, saveCookie: true/false) { postRequestStatus in
// ... code that will run once the request is done
})
方法看起来很奇怪,我没有仔细检查过,但是我认为虽然postRequest
是其中一个参数,但实际上并没有使用它。其他一些答案将其他问题指向该功能。