This code is about getting data from a website.
In the playground, when I execute all of this code at once,
numberOfResults gives me a value of zero which is a default value as shown above.
When I execute getDataFrom(link:link) first and then print(numberOfResults), it gives me the value I want which shows that print function is executed before the task in getDataFrom function is fully executed.
Is there any way to access numberOfResults variable after the task has been fully executed?
Also, I tried to handle this order problem by calling the function
in @main to be executed first when the app is launched in my project but there was a time delay to access the data (when I access the var right away, it will give me default value while it gives me the value I want only after accessing the var few second after) so I want to ask if there is a way to shorten the time taken to execute dataTask.
Code Block var numberOfResults = 0 func getDataFrom(link:String) { guard let url = URL(string:link) else { return } let endPoint = NSMutableURLRequest(url: url) let task = URLSession.shared.dataTask(with: endPoint as URLRequest) { (data,response,error) in guard let data = data else { print("\(Fatal_Error.dataNotFound)") return } guard response != nil, error == nil else { print("\(Fatal_Error.noResponse)") return } var jsonData:fetchData? do { jsonData = try JSONDecoder().decode(fetchData.self, from: data) guard let existingData = jsonData else { return } numberOfResults = existingData.totalResults print(numberOfResults) } catch { jsonData = nil } } task.resume() } getDataFrom(link: link) print(numberOfResults)
In the playground, when I execute all of this code at once,
numberOfResults gives me a value of zero which is a default value as shown above.
When I execute getDataFrom(link:link) first and then print(numberOfResults), it gives me the value I want which shows that print function is executed before the task in getDataFrom function is fully executed.
Is there any way to access numberOfResults variable after the task has been fully executed?
Also, I tried to handle this order problem by calling the function
in @main to be executed first when the app is launched in my project but there was a time delay to access the data (when I access the var right away, it will give me default value while it gives me the value I want only after accessing the var few second after) so I want to ask if there is a way to shorten the time taken to execute dataTask.
URLSession is an async API. That is, you make a request and at some point in the future it calls the completion handler with the response. Code like this:
won’t work because the request is still in flight at the time you print numberOfResults on line 3.
How you handle this very much depends on the context. If you’re working in a playground you might use code like that shown below. However, in a real product you’d adopt a technique that’s aligned with your overall architecture. For example:
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Code Block getDataFrom(link: link) print(numberOfResults)
won’t work because the request is still in flight at the time you print numberOfResults on line 3.
How you handle this very much depends on the context. If you’re working in a playground you might use code like that shown below. However, in a real product you’d adopt a technique that’s aligned with your overall architecture. For example:
In a toy project you might use the synthetic synchronous approach.
In a real app you might use Combine to process async data and apply it to your model. See Processing URL Session Data Task Results with Combine.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Code Block import Foundation import PlaygroundSupport func load(url: URL, completionHandler: @escaping (Result<HTTPURLResponse, Error>) -> Void) { let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 60.0) URLSession.shared.dataTask(with: request) { (data, response, error) in let result: Result<HTTPURLResponse, Error> if let error = error as NSError? { result = .failure(error) } else { let response = response as! HTTPURLResponse let data = data! _ = data // ignore `data` for the moment result = .success(response) } DispatchQueue.main.async { completionHandler(result) } }.resume() } PlaygroundPage.current.needsIndefiniteExecution load(url: URL(string: "https://example.com")!) { result in print(result) PlaygroundPage.current.finishExecution() }