I cannot return data from my HTTPrequest and I can't get completion handlers to work either. So please assist me in my quest to solve this issue:
public static func createRequest(qMes: message, location: String, method: String) -> String{
let requestURL = URL(string: location)
var request = URLRequest(url: requestURL!)
request.httpMethod = method
request.httpBody = qMes.toString().data(using: .utf8)
let requestTask = URLSession.shared.dataTask(with: request) {
(data: Data?, response: URLResponse?, error: Error?) in
if(error != nil) {
print("Error: \(error)")
}
return String(data: data!, encoding: String.Encoding.utf8) as String!
}
requestTask.resume()
}
It is excpecting non-void return statement in void function. At this point I'm clueless...
You can use this completion block method to send the final response:
For Instance: I have returned String in completion block, after successful response without error just pass the result in block.
public func createRequest(qMes: String, location: String, method: String , completionBlock: @escaping (String) -> Void) -> Void
{
let requestURL = URL(string: location)
var request = URLRequest(url: requestURL!)
request.httpMethod = method
request.httpBody = qMes.data(using: .utf8)
let requestTask = URLSession.shared.dataTask(with: request) {
(data: Data?, response: URLResponse?, error: Error?) in
if(error != nil) {
print("Error: \(error)")
}else
{
let outputStr = String(data: data!, encoding: String.Encoding.utf8) as String!
//send this block to required place
completionBlock(outputStr!);
}
}
requestTask.resume()
}
You can use this below code to execute the above completion block function:
self.createRequest(qMes: "", location: "", method: "") { (output) in
}
This will solve your following requirement.
{
(data: Data?, response: URLResponse?, error: Error?) in
if(error != nil) {
print("Error: \(error)")
}
return String(data: data!, encoding: String.Encoding.utf8) as String!
}
This part of your code is the completion handler for the dataTask()
method. It's a block of code that you pass into the dataTask()
method to be executed later on (when the server sends back some data or there's an error). It's not executed straight away.
This means that when your createRequest()
method above is executing, it passes straight over that code, then onto the requestTask.resume()
line, and then the method ends. At that point, because your method is defined as returning a String
, you need to return a String
. Returning it from the completion handler is no good because that hasn't been executed yet, that is going to be executed later on.
There's lots of different ways to handle asynchronous programming, but one way of tackling this is to change your createRequest()
method so that it isn't defined to return a String
, create a method that takes a String
as a parameter which does whatever you wanted to do with the return value, and then call that method from your completion handler.
Instead of using return, try using completion handlers as you mentioned in your question.
func createRequest(qMes: message, location: String, method: String, completionHandler: @escaping (_ data:Data?, _ response: URLResponse?, _ error: NSError?) -> Void)
Then instead of return
you should use something like completionHandler(data, response, error)
And this is how you make the request:
var request = URLRequest(url: Foundation.URL(string: URL)!)
request.httpMethod = method
//request.addValue(authString, forHTTPHeaderField: "Authorization") // if you need some
let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
guard error == nil && data != nil else
{
print("error=\(error)")
completionHandler(data, response, error as NSError?)
return
}
completionHandler(data, response, error as NSError?)
})
task.resume()
Just in your function call
var webString = try String(contentsOf: URL(string: url)!)
And you have full response in string, that you can return
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With