NSURLSessionDataTask does not return data from request - ios

I'm trying to make a request to a server, which should return data that I can use in the rest of my application. Here is my code:
func makeNewUser() -> NSDictionary {
var full_url = getFullUrl("makeNewUser")
var toReturn: NSDictionary = NSDictionary()
var request: NSURLRequest = NSURLRequest(URL:full_url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession.sharedSession()
let task : NSURLSessionDataTask = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
println(response)
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if(err != nil) {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
toReturn = jsonResult
});
task.resume()
self.delegate?.didReceiveAPIResults(toReturn)
println(toReturn)
return toReturn
}
I am sending toReturn data to a delegate function in the caller, but it is not available. I believe the reason for this is because the request is asynchronous. What is the proper way for me to handle this so that the caller knows to wait for this data before continuing?

move the delegate call into the session completion block:
func makeNewUser() {
var full_url = getFullUrl("makeNewUser")
var toReturn: NSDictionary = NSDictionary()
var request: NSURLRequest = NSURLRequest(URL:full_url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession.sharedSession()
let task : NSURLSessionDataTask = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
println(response)
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if(err != nil) {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
self.delegate?.didReceiveAPIResults(jsonResult) // <<-----
});
task.resume()
}
And you just have to be aware that the result is not immediately available. You don't want to block the function (and UI) on long running operations like network requests anyway.

Related

Getting Header Response in Swift

I am following this answer for making HTTP calls in my swift project. How to make an HTTP request in Swift?
and following is the code I am using to make a synchronous call
let urlPath: String = "http://apiserver.com/api/login/?username=asdf&password=asdf"
var url: NSURL = NSURL(string: urlPath)!
var request1: NSURLRequest = NSURLRequest(URL: url)
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?> = nil
var error: NSErrorPointer = nil
var dataVal: NSData = NSURLConnection.sendSynchronousRequest(request1, returningResponse: response, error:nil)!
var err: NSError
println("response -- \(response)")
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataVal, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary
println("Synchronous \(jsonResult)")
is here anyone who can help me to get HTTP Header Response or status code by using this code? please
Try this:
func getData(url: NSURL) {
let config: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session: NSURLSession = NSURLSession(configuration: config)
let dataTask: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: {(data: NSData!, urlResponse: NSURLResponse!, error: NSError!) -> Void in
if let httpUrlResponse = urlResponse as? NSHTTPURLResponse
{
if error {
println("Error Occurred: \(error.localizedDescription)")
} else {
println("\(httpUrlResponse.allHeaderFields)") // Error
}
}
})
dataTask.resume()
}
Per your code in the original question, have you tried this?
let urlPath: String = "http://apiserver.com/api/login/?username=asdf&password=asdf"
var url: NSURL = NSURL(string: urlPath)!
var request1: NSURLRequest = NSURLRequest(URL: url)
var response: NSURLResponse? = nil
var error: NSError? = nil
var dataVal: NSData = NSURLConnection.sendSynchronousRequest(request1, returningResponse: &response, error:&error)!
var err: NSError
println("response -- \(response)")
if let response = response as? NSHTTPURLResponse {
if response.statusCode == 200 {
print("Success")
}
}
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataVal, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary
println("Synchronous \(jsonResult)")
Extension to retrive header field
extension URLResponse {
func headerField(forKey key: String) -> String? {
(self as? HTTPURLResponse)?.allHeaderFields[key] as? String
}
}
Usage
var urlResponse: URLResponse = ...
let headerField = urlResponse.headerField(forKey: "retry-after")

Delay in displaying data on tableView in ios swift

Hi,
I'm trying to parse data on to the listview and am able to get it and
display it on the tableView but the problem is it is taking hell lot
of time to display it on the tableview. Please find the my code below.
func jsonParsing()
{
activityIndicatorView.startAnimating()
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest (URL: deviceListURL)
request.HTTPMethod = "GET"
let task = session.dataTaskWithRequest(request, completionHandler: {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)
}
var err: NSError?
if(data != nil) {
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as! NSMutableArray
//println("Data: \(jsonResult)")
var dataDict: NSDictionary
for dataDict : AnyObject in jsonResult {
var device_id: NSString = dataDict.objectForKey("deviceId") as! NSString
var device_name: NSString = dataDict.objectForKey("deviceName") as! NSString
var device_status: NSInteger = dataDict.objectForKey("status") as! NSInteger
let dictionary = [self.deviceID: device_id, self.deviceName: device_name, self.Status: device_status]
self.myObject.addObject(dictionary)
}
println("My object = %#", self.myObject)
println(self.myObject.count)
if self.myObject.count != 0 {
self.reloadTable()
}
}
if err != nil {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
})
task.resume()
}
The completion handler is running in a background queue, not the main thread. UI updates have to happen on the main thread, though.
Try calling reloadTable() on the main thread:
dispatch_sync(dispatch_get_main_queue(), {
self.reloadTable()
})
(I just typed this in here untested, so I hope it works this way)

JSON Data is not returning as a string in swift

I am trying to return data from JSON object as a string but whenever I try it returns nil if someone could help please find the below code. I need to return currentWeather as a String with its value currently I am not able to return the data as a string only as an optional.
let urlPath = "http://api.openweathermap.org/data/2.5/weather?q=London,uk&units=metric"
let url: NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
println("Task completed")
if((error) != nil) {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
let jsonDictionary = jsonResult as NSDictionary
let mainDictionary = jsonResult.valueForKey("main") as NSDictionary
let currentWeather = mainDictionary.valueForKey("humidity") as? NSString
println(currentWeather)
})
task.resume()
I tried the code. The 'humidity' is an Int, not String. So you should use
let currentWeather = mainDictionary.valueForKey("humidity") as Int

How to return the data type: NSDictionary in Swift

I want to return the data type: NSDictionary. But main code got empty NSDictionary.
How can I solve this problem? I used JSON method in the function.
func regionDataReturn(rid: Int) -> NSDictionary {
var jsonResult: NSDictionary = NSDictionary()
let urlPath: String = "MY_SERVER/test.php"
var url: NSURL = NSURL(string: urlPath)!
var request1: NSMutableURLRequest = NSMutableURLRequest(URL: url)
request1.HTTPMethod = "POST"
var stringPost="test_id=\(tid)" // Key and Value
let data = stringPost.dataUsingEncoding(NSUTF8StringEncoding)
request1.timeoutInterval = 60
request1.HTTPBody=data
request1.HTTPShouldHandleCookies=false
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request1, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var err: NSError
jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
self.navigationItem.title = jsonResult["name"] as? String
NSLog("\(self.navigationItem.title)")
})
return jsonResult
}
You can't do like that.
You are calling a asynchronous function for getting the data, your method will return before the data is fetched. You have two option to fix this issue:
Use notification, pass a completion handler or out parameter to pass the value back to called method
Make it a synchronous call
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?> = nil
var error: NSErrorPointer = nil
var data : NSData = NSURLConnection.sendSynchronousRequest(request1, returningResponse: response, error:nil)!
var err : NSError
jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
self.navigationItem.title = jsonResult["name"] as? String
NSLog("\(self.navigationItem.title)")

Swift IOS: How to perform a REST POST request

I am trying to implement a POST with raw text to path, I have tried using NSMutableURLRequest and specifying the following
request.HTTPMethod = "POST"
request.HTTPBody = "some strings here"
I did not manage to get much further than that as I failed miserably while implementing the session.uploadTaskWithRequest.
This however is what I got working fine for a GET request;
private func get(path: String)
{
let url = NSURL(string: path)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
println("JSON recieved")
if(error)
{
println(error.localizedDescription)
}
println("Parsing JSON")
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if(err != nil)
{
println("Json error");
}
println("Building Array result list from JSON")
var results = jsonResult["results"] as NSArray
self.delegate?.didReceiveAPIResult(jsonResult)
println("Done with JSON response")
})
task.resume()
}
Here you go:
let request = NSMutableURLRequest(URL: yourURL)
request.HTTPMethod = "POST"
let data = yourString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().uploadTaskWithRequest(request,
fromData: data)
task.resume()

Resources