从异步调用中返回数据,该函数在Swift函数

时间:2017-05-16 05:26:43

标签: swift

我正在尝试创建一个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)
    })
}

2 个答案:

答案 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手册,详细了解closuresfunctions

顺便说一句,你的postRequest(url: yourUrlObject, request: yourUrlRequest, saveCookie: true/false) { postRequestStatus in // ... code that will run once the request is done }) 方法看起来很奇怪,我没有仔细检查过,但是我认为虽然postRequest是其中一个参数,但实际上并没有使用它。其他一些答案将其他问题指向该功能。