Function with Datatask Returning a Value

function with dataTask returning a value

in order to return value you should use blocks. Try declaring your function like this:

class func checkUrl(urlString: String, finished: ((isSuccess: Bool)->Void) {

let urlPath: String = urlString
var url: NSURL = NSURL(string: urlPath)!
var request: NSURLRequest = NSURLRequest(url: url as URL)
var response: URLResponse?

let session = Foundation.URLSession.shared


var task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}

if let data = data{
print("data =\(data)")
}
if let response = response {
print("url = \(response.url!)")
print("response = \(response)")
let httpResponse = response as! HTTPURLResponse
print("response code = \(httpResponse.statusCode)")

if httpResponse.statusCode == 200{
finished(isSuccess: true)
} else {
finished(isSuccess: false)
}
}
})
task.resume()
}

And then call it like this:

checkUrl("http://myBestURL.com", finished { isSuccess in
// Handle logic after return here
})

Hope that this will help.

Returning values URLSession.shared.dataTask in swift

You can use completion block to return value. Add completion block your to function like this

func parse (latitude: Double, longtitude: Double, completion: @escaping ((AnyObject) -> Void)){
let jsonUrlString = "https://api.darksky.net/forecast/apiKey/\(latitude),\(longtitude)"

guard let url = URL(string: jsonUrlString) else{
return
}

var information: forecast?
URLSession.shared.dataTask(with: url) { (data, res, err) in

guard let data = data else {
return
}

do {
let json = try JSONDecoder().decode(forecast.self, from: data)
self.info = json
completion(info)
} catch {
print("didnt work")
}

}.resume()

And when you call this function, it return your info

parse( lat, long, {info in
processJson(info)
})

How to wait until data from network call comes and only then return value of a function #Swift

I think that you were on the right path when attempting to use a completion block, just didn't do it correctly.

func loadList(at page: Int, completion: @escaping ((Error?, Bool, [Beer]?) -> Void)) {
//MARK: - Checks is URL is valid + pagination
guard let url = URL(string: "https://api.punkapi.com/v2/beers?page=\(page)&per_page=25") else {
print("Invalid URL")
completion(nil, false, nil)
return
}
//MARK: - Creating URLSession DataTask
let task = URLSession.shared.dataTask(with: url){ data, response, error in
//MARK: - Handling no erros came
if let error = error {
completion(error, false, nil)
print(error!)
return
}
//MARK: - Handling data came
guard let data = data, let beers = try? JSONDecoder().decode([Beer].self, from: data) else {
completion(nil, false, nil)
return
}
completion(nil, true, beers)
}
task.resume()
}

This is the loadList function, which now has a completion parameter that will have three parameters, respectively the optional Error, the Bool value representing success or failure of obtaining the data, and the actual [Beers] array, containing the data (if any was retrieved).

Here's how you would now call the function:

service.loadList(at: page) { error, success, beers in
if let error = error {
// Handle the error here
return
}

if success, let beers = beers {
// Data was correctly retrieved - and safely unwrapped for good measure, do what you need with it
// Example:
loader.stopLoading()
self.datasource = beers
self.tableView.reloadData()
}
}

Bear in mind the fact that the completion is being executed asynchronously, without stopping the execution of the rest of your app.
Also, you should decide wether you want to handle the error directly inside the loadList function or inside the closure, and possibly remove the Error parameter if you handle it inside the function.
The same goes for the other parameters: you can decide to only have a closure that only has a [Beer] parameter and only call the closure if the data is correctly retrieved and converted.

Returning generic type from a URLRequest dataTask

You have to declare

func loadFrom<T: Decodable>(url: String, memberType: T.Type, completionHandler: @escaping (T?) -> Void) {

and call it

loadFrom(url: "https://jsonplaceholder.typicode.com/todos?completed=true", memberType: Todo.self) {response in
...
}

And rather than the unhandy fatal errors add a better result type to be able to return also the errors and catch the bad URL before calling the method

func loadFrom<T: Decodable>(url: URL, memberType: T.Type, completionHandler: @escaping (Result<T,Error>) -> Void) {
URLSession.shared.dataTask(with: url) {data, _, error in
if let error = error {
completionHandler(.failure(error))
} else {
completionHandler( Result{ try JSONDecoder().decode(T.self, from: data!)})
}
}.resume()
}

Can I use URLSession in a function with return?

You cant return because a network requests happen asychronously. Instead of using a return, use a closure that is called when the request has completed. Check out the following:

func sendRequest(_ _request:URLRequest, completion:@escaping (_ success:Bool,_ error:Error?, _ _data:[String:AnyObject]?)->Void) -> URLSessionDataTask {
let session:URLSession = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: self.queue)
let task:URLSessionDataTask = session.dataTask(with: _request) { (_data, _response, _error) in
if let resultsDic:[String:AnyObject] = self.parseJSONFromData(retrievedData, withInitalKey: self.getInitialKey()){
completion(true, nil, resultsDic)
} else {
completion(false, nil, nil)
}
}
task.resume()
return task
}

swift function doesnt return a value

In order to know what is happening here, you need to learn about @escaping functions in swift, here is some link1 together with taking function as another functions parameter link2 written in part "Function Types as Parameter Types" , closures in Swift link3 and
Here is what is happening simplified and explained step by step :

  1. you call getAnswer()

  2. variable answer gets initialized with value nil by declaring answer: String?

  3. URLSession.shared.dataTask is called and it is taking as an argument another function - closure (Data?, URLResponse?, Error?) -> Void . Also URLSession.shared.dataTask is executed on different thread and is not returning yet, but will return right after it receives response from server, which can take any time (but usually milliseconds) and will basically happen after your getAnswer() function is returning value.

  4. your getAnswer() immediately returns value of answer which is currently nil

  5. if you get any data from server, or server could not be reached, your URLSession.shared.dataTask function executes your code in closure. This is the code it will execute:

             guard let data = data, error == nil else {
    return
    }

    guard let response = response as? HTTPURLResponse else { return }

    guard response.statusCode == 200 else { return }

    do {
    let model = try JSONDecoder().decode(Answer.self, from: data)

    DispatchQueue.main.async {
    answer = model.magic.answer
    }
    } catch let error {
    fatalError(error.localizedDescription)
    }


Related Topics



Leave a reply



Submit