How to Pass Variable Value to Outside of Urlsession Async - Swift 3

how to pass variable value to outside of URLSession async - swift 3

You have several methods to tackle the issue of returning a value from inside an asynchronous function. One of them is to wrap the asynchronous network call inside a function and make it return a completionHandler.

Some general advice: don't use force unwrapping unless you are 100% sure that your optional value won't be nil. With network requests, the data can be nil even if there's no error, so never force unwrap data, use safe unwrapping with if let or guard let. Don't use .mutableContainers in Swift when parsing a JSON value, since it has no effect. The mutability of the parsed JSON object is decided by using the let or var keyword to declare the variable holding it. Also don't use NSDictionary, use its native Swift counterpart, Dictionary ([String:Any] is a shorthand for the type Dictionary<String,Any>).

func getDetail(withRequest request: URLRequest, withCompletion completion: @escaping (String?, Error?) -> Void) {
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil {
completion(nil, error)
return
}
else if let data = data {
do {
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] else {completion(nil, nil);return}
guard let details = json["detail"] as? String else {completion(nil, nil);return}
completion(details, nil)
}
catch {
completion(nil, error)
}
}
}
task.resume()
}

Then you can call this function by

getDetail(withRequest: request, withCompletion: { detail, error in
if error != nil {
//handle error
} else if detail = detail {
//You can use detail here
}
})

Pass variable to dataTask async function

For this purpose DispatchGroup is the recommended API for example

var neededVariable = 1
let group = DispatchGroup()
let session = URLSession.shared
for _ in 0...10 {
group.enter()
let urlS = "https://sub2pewdiepie.com/subscribe.php?param1=123"
let url = URL(string: urlS.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!)!

let task = session.dataTask(with: url, completionHandler: { data, response, error in
defer(group.leave())
if let error = error { print(error); return }
do {
neededVariable += 1
print(neededVariable)
} catch let error { print(error.localizedDescription) }
})
task.resume()

}

group.notify(queue: DispatchQueue.main) {
print("notify", neededVariable)
}

Appending a variable outside the scope of a function in Swift 3

You are dealing with asynchronous code. You should not use an inout parameter. Instead, you should be using a completion handler.

Something like the following will work:

var jsonFile: [String] = []

func function(completion: @escaping (String?) -> Void) {
var request = URLRequest(url: URL(string: "https://parse.udacity.com/parse/classes/StudentLocation?limit=1")!)
request.addValue("QrX47CA9cyuGewLdsL7o5Eb8iug6Em8ye0dnAbIr", forHTTPHeaderField: "X-Parse-Application-Id")
request.addValue("QuWThTdiRmTux3YaDseUSEpUKo7aBYM737yKd4gY", forHTTPHeaderField: "X-Parse-REST-API-Key")
let session = URLSession.shared
let task = session.dataTask(with: request) { data, response, error in
if let data = data, error != nil {
if let jsonData = String(data: data, encoding: .utf8) {
completion(jsonData)
} else {
completion(nil)
}
} else {
completion(nil)
}
}
task.resume()
}

function() { (string) in
if let string = string {
jsonFile.append(string)
}

print(jsonFile)
}

Note all of the other clean up. Don't use NSString, use String. Don't use NSMutableURLRequest, use URLRequest with var.

How i can pass the data to a variable in swift4?

You can try this as the process is asynchronous

func callApi(_ postString: String,completion:@escaping:(_ res:String?) -> Void ) {
var req = LogIn(postString: postString)
URLSession.shared.dataTask(with: req) { (data, response, error) in
if let data = data{
completion(String(data: data, encoding: String.Encoding.utf8))
}
else {
completion(nil)
}
}.resume()
}

Call

callApi("SendedValue") {  res in
print(res)
}

Swift 3: how to return values out of session.uploadTask

The completion handler to call when the load request is complete. This handler is executed on the delegate queue.This completion handler takes the following parameters:

data
The data returned by the server.
response
An object that provides response metadata, such as HTTP headers and status code. If you are making an HTTP or HTTPS request, the returned object is actually an HTTPURLResponse object.
error
An error object that indicates why the request failed, or nil if the request was successful.

Swift: How do I return a value within an asynchronous urlsession function?

You should add your own completionHandler closure parameter and call it when the task completes:

func googleDuration(origin: String, destination: String, completionHandler: (Int?, NSError?) -> Void ) -> NSURLSessionTask {
// do calculations origin and destiantion with google distance matrix api

let originFix = origin.stringByReplacingOccurrencesOfString(" ", withString: "+", options: NSStringCompareOptions.LiteralSearch, range: nil);
let destinationFix = destination.stringByReplacingOccurrencesOfString(" ", withString: "+", options: NSStringCompareOptions.LiteralSearch, range: nil);

let urlAsString = "https://maps.googleapis.com/maps/api/distancematrix/json?origins="+originFix+"&destinations="+destinationFix
println(urlAsString)

let url = NSURL(string: urlAsString)!
let urlSession = NSURLSession.sharedSession()

let task = urlSession.dataTaskWithURL(url) { data, response, error -> Void in
if error != nil {
// If there is an error in the web request, print it to the console
// println(error.localizedDescription)
completionHandler(nil, error)
return
}

//println("parsing JSON");
let json = JSON(data: data)
if (json["status"].stringValue == "OK") {
if let totalTime = json["rows"][0]["elements"][0]["duration"]["value"].integerValue {
// println(totalTime);
completionHandler(totalTime, nil)
return
}
let totalTimeError = NSError(domain: kAppDomain, code: kTotalTimeError, userInfo: nil) // populate this any way you prefer
completionHandler(nil, totalTimeError)
}
let jsonError = NSError(domain: kAppDomain, code: kJsonError, userInfo: nil) // again, populate this as you prefer
completionHandler(nil, jsonError)
}
task.resume()
return task
}

I'd also have this return the NSURLSessionTask in case the caller wants to be able to cancel the task.

Anyway, you'd call this like so:

googleDuration(origin, destination: destination) { totalTime, error in
if let totalTime = totalTime {
// use totalTime here
} else {
// handle error
}
}


Related Topics



Leave a reply



Submit