swift tableview displays json data very slow - json

I have a page that loops JSON data and show in a tableview.
I get the correct correctly but when it shows on the page, it is very slow.
I tried to println the json to see how fast it retrieves the json data and it was very fast.
One more thing which is very odd is when it is loading, if I drag the page, everything will show instantly.
Below is the code I put in viewdidload function
self.PoTable.separatorStyle = UITableViewCellSeparatorStyle(rawValue: 0)!
self.navigationController?.navigationBar.topItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
PoTable.delegate = self
PoTable.dataSource = self
self.PoTable.addSubview(self.activityIndicatorView)
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
activityIndicatorView.startAnimating()
let url = NSURL(string: SharedClass().clsLink + "/json/POList.cfm")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, 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?
let res = response as! NSHTTPURLResponse!
if(res != nil){
if (res.statusCode >= 200 && res.statusCode < 300){
self.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)")
}
var resultsArr: NSArray = self.jsonResult["results"] as! NSArray
// println(resultsArr)
self.PoList = PoInfo.poInfoWithJSON(resultsArr)
self.PoTable!.reloadData()
self.activityIndicatorView.stopAnimating()
self.activityIndicatorView.hidden = true
}
else{
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
SharedClass().serverAlert(self)
}
}else{
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
self.activityIndicatorView.stopAnimating()
SharedClass().serverAlert(self)
}
})
task.resume()
please help

try this async scope dispatch_async(dispatch_get_main_queue()) in your if closure like
dispatch_async(dispatch_get_main_queue()) {
if (res.statusCode >= 200 && res.statusCode < 300){
self.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)")
}
var resultsArr: NSArray = self.jsonResult["results"] as! NSArray
self.PoList = PoInfo.poInfoWithJSON(resultsArr)
self.PoTable!.reloadData()
self.activityIndicatorView.stopAnimating()
self.activityIndicatorView.hidden = true
}
}

Related

response Data is nil

I am getting response data nil.
func fetchSinglePageData() {
var response: NSData?
var errors: NSError?
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
response = NSData(contentsOfFile:"url...?project_id=(self.projectID)&project_page=Request", options: NSDataReadingOptions(0), error: &errors)
print("LatestURL Single page:(response)")
if response == nil {
var alertview = UIAlertView(title: "Network Error", message: "Data not received due to network connection.Try again...", delegate: self, cancelButtonTitle: "Ok")
alertview.show()
}
else{
let jsonDict: NSDictionary = NSJSONSerialization.JSONObjectWithData(response!, options: nil, error: &errors) as NSDictionary
print("JSON Response Single page:(jsonDict)")
var statuses = [NSObject : AnyObject]()
self.lblstartTime?.text = jsonDict["start_time"] as? String
self.lblcurrentStage?.text = jsonDict["current_stage"] as? String
self.lblcompletionTime?.text = jsonDict["completion_time"] as? String
self.lblManager?.text = jsonDict["manager"] as? String
}
})
}
project_id is string which is recevied from presvious page which is correctly working.
In swift 3
//make a url request
let urlString = "your_url"
let urlRequest = URLRequest.init(url: URL.init(string: urlString)!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 50)
//create a session
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, urlResponse, error) in
if error != nil{
//handle error
return
}else{
if let responseData = data{
let jsonDict = try JSONSerialization.jsonObject(with: responseData, options: [])as? [String:Any]
//handle your response here
}
}
}
task.resume()
In swift 2.2
let urlString = "your_url"
let request = NSURLRequest(URL: NSURL(string: urlString)!, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 50)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { (data, response, error) in
if error != nil{
//handel error
print(error!.localizedDescription)
return
}
if let responseData = data{
do{
if let jsonDict = try NSJSONSerialization.JSONObjectWithData(responseData, options: [])as? [String:Any]{
//you have data in json dict
}
}catch{
print("error in parsing response")
return
}
}
}
task.resume()
func singlePageData(){
var errors: NSError?
let urlString = "xyz.com"
print("URL RESPONSE \(urlString)")
let request = NSURLRequest(URL: NSURL(string: urlString), cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 50)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { (data, response, error) in
if error != nil{
//handel error
print(error!.localizedDescription)
var alertview = UIAlertView(title: "Network Error", message: "Data not received due to network connection.Try again...", delegate: self, cancelButtonTitle: "Ok")
alertview.show()
return
}
if let responseData = data{
var jsonDict: NSDictionary = NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.MutableContainers, error: &errors) as NSDictionary!
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
println("Json dict value \(jsonDict)")
self.lblprojectName?.text = jsonDict["name"] as? String
println("lblprojectName: \(self.lblprojectName?.text)")
self.lblstartTime?.text = jsonDict["start_time"] as? String
println("lblstartTime : \(self.lblstartTime?.text)")
self.lblcurrentStage?.text = jsonDict["current_stage"] as? String
println("lblcurrentStage : \(self.lblcurrentStage?.text)")
self.lblcompletionTime?.text = jsonDict["completion_time"] as? String
println("lblcompletionTime : \(self.lblcompletionTime?.text)")
self.lblManager?.text = jsonDict["manager"] as? String
})
}
}
task.resume()
}
This is my answer as per Jitendra Solanki answer i have made changes to code and it is now working in Swift 1.2
After a quick look, maybe \ missing:
NSData(contentsOfFile:"url...?project_id=\(self.projectID)&project_page=Request"
In this line:
response = NSData(contentsOfFile:"url...?project_id=(self.projectID)&project_page=Request", options: NSDataReadingOptions(0), error: &errors)
you have project_id=(self.projectID), to use interpolation you should instead have project_id=\(self.projectID)
I would suggest that you separate the code to generate your full URL, then print the URL to the console and ensure that it is what you would expect.
Then you can visit the url yourself and check to see what the server returns, then once you know you have the correct URL and response you can then work to deserialise the response
EDIT: updated with URLSession (Swift 3 version)
let defaultSession = URLSession(configuration: URLSessionConfiguration.default)
var dataTask: URLSessionDataTask?
let projectID = 12
let url = URL(string: "http://phpyouth.com/clients/halfpricedgrannyflats/app/app_response.php?project_id=\(projectID)&project_page=Request")
dataTask = defaultSession.dataTask(with: url!) {
data, response, error in
if let error = error {
print(error.localizedDescription)
} else if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
if let responseData = data {
if let json = try? JSONSerialization.jsonObject(with: responseData, options: .allowFragments) as? [String:AnyObject] {
print(json)
}
}
}
}
}
dataTask?.resume()

JSON parse error: The data couldn’t be read because it isn’t in the correct format

I am new to Xcode and Swift and have the below code that shows error on print(parseJSON).
Error: The data couldn’t be read because it isn’t in the correct
format.
The code is posting data correctly to the server, but the response cannot be parsed.
JSON response from my ASMX page:
{"status":"Success","message":"User is registered"}
Any help will be appreciated.
// Send data to server side
let myURL = NSURL(string: "http://www.examle.com/Info.asmx/Testing")
let request = NSMutableURLRequest(URL: myURL!)
request.HTTPMethod = "POST"
let postString = "Email=\(userEmail!)&Password=\(userPassword!)"
print(postString)
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){
data, response, error in
if error != nil {
print("error=\(error)")
return
}
//var err: NSError?
do{
if let parseJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary{
print(parseJSON) // ERROR HERE
let resultValue = parseJSON["status"] as? String
print("result: \(resultValue)")
var isUserRegistered:Bool = false
if (resultValue == "Success") {
isUserRegistered = true
}
var messageToDisplay:String = parseJSON["message"] as! String!
if (!isUserRegistered){
messageToDisplay = parseJSON["message"] as! String!
}
dispatch_async(dispatch_get_main_queue(), {
let myAlert = UIAlertController(title: "Alert", message: messageToDisplay, preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default){ action in
self.dismissViewControllerAnimated(true, completion: nil)
}
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
})
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
task.resume()

Swift: JSON file from URL instead of local

Right now I have this:
let path : String = NSBundle.mainBundle().pathForResource("jsonFile", ofType: "json") as String!
let jsonData = NSData(contentsOfFile: path) as NSData!
let readableJSON = JSON(data :jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)
But I want to receive the file from a url, and not have it in my app.
You need to read through some of apple docs: NSURLConnection and NSURLSession
Here is a quick solution for how to achieve this though.
func fetchDetailsFromServer() {
let urlPath = "Server URL to Fetch JSON"
let url = 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?
if let 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)")
}
// Use your jsonResult appropriately here
}
})
// The task is just an object with all these properties set
// In order to actually make the web request, we need to "resume"
task.resume()
}

Do action on JSON complete

I have written a function that makes a JSON request and puts the result in three arrays.
I want to present a view controller after this JSON request is completed fully.
I tried putting the action below the for-in loop, but this didn't work.
This is my code:
func getJSON() {
var vc = self.storyboard?.instantiateViewControllerWithIdentifier("myVCId") as ViewController
let urlAsString = "http://localhost:8888/domainchecker/check.php?domain=/" + tfDomain.text;
println(urlAsString);
let url = NSURL(string: urlAsString)!
let urlSession = NSURLSession.sharedSession()
let jsonQuery = urlSession.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
if (error != nil) {
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if (err != nil) {
println("JSON Error \(err!.localizedDescription)")
}
let arrayFromJson: [[String:String]] = jsonResult["ITEMS"] as [[String:String]]
dispatch_async(dispatch_get_main_queue(), {
for item in arrayFromJson {
vc.tableData.append(item["DOMAIN"]!);
vc.tablePrice.append(item["PRICE"]!);
vc.tableAvailability.append(item["AVAILABLE"]!);
}
self.presentViewController(vc, animated: true, completion: nil)
})
})
jsonQuery.resume()
}
This is the action I want to do after the code has completed:
self.presentViewController(vc, animated: true, completion: nil)
if (arrayFromJson.count > 0) {
self.presentViewController(vc, animated: true, completion: nil)
}
this is it.

Get JSON data function - Address noch reachable - NSURLErrorDomain error -1002

I have a function to retrieve JSON data from an certain ip address.
if the ip is not reachable, xcode gives me following error at
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
The operation couldn’t be completed. (NSURLErrorDomain error -1002.) fatal error: unexpectedly found nil while unwrapping an Optional value
How can I check, if jsonResult is valid or if ip-address is valid?
func getJsonData() {
let urlAsString = NSUserDefaults.standardUserDefaults().objectForKey("ipAddress") as String
let url: NSURL = NSURL(string: urlAsString)!
let urlSession = NSURLSession.sharedSession()
let jsonQuery = urlSession.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
if (error != nil) {
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if (err != nil) {
println("JSON Error \(err!.localizedDescription)")
}
//Display Data
dispatch_async(dispatch_get_main_queue(), {
self.label.text = String(format: "%.3f", (jsonResult["pwr"] as Float!)/1000)
})
})
jsonQuery.resume()
}
Thanks!
if (error != nil) {
println(error.localizedDescription)
}
It's not enough to print an error to debugger console. The error must be handled. Ask yourself - what do you want to do if there is no internet connection? Do you want to display an error to the user? Try to send the request again?
The basic fact is that if there was an error, you cannot continue and parse the data. The data is not there, it was not loaded. If you try to parse the data (which is nil), your app will crash.
if (error != nil) {
//XXX: display error to the user, e.g. using an alert
return; //return immediately, don't proceed to parsing.
}
Create a method like below to check valid url.
func validateUrl (stringURL : NSString) -> Bool {
var urlRegEx = "((https|http)://)((\\w|-)+)(([.]|[/])((\\w|-)+))+"
let predicate = NSPredicate(format:"SELF MATCHES %#", argumentArray:[urlRegEx])
var urlTest = NSPredicate.predicateWithSubstitutionVariables(predicate)
return predicate.evaluateWithObject(stringURL)
}
And then update your method. Add a line to call validate url method.
func getJsonData() {
let urlAsString = NSUserDefaults.standardUserDefaults().objectForKey("ipAddress") as String
var isValidURL = validateUrl(urlAsString)
if (!isValidURL) {
// Return from here. URL is invalid
return
}
let url: NSURL = NSURL(string: urlAsString)!
let urlSession = NSURLSession.sharedSession()
let jsonQuery = urlSession.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
if (error != nil) {
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if (err != nil) {
println("JSON Error \(err!.localizedDescription)")
}
//Display Data
dispatch_async(dispatch_get_main_queue(), {
self.label.text = String(format: "%.3f", (jsonResult["pwr"] as Float!)/1000)
})
})
jsonQuery.resume()
}