Do action on JSON complete - json

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.

Related

Swift login screen performing segue

I am using following code to login users first user enters password and id then using post request I am sending this information to the server.
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
let message2 = "Please wait..."
var messageMutableString = NSMutableAttributedString()
messageMutableString = NSMutableAttributedString(string: message2 as String, attributes: [NSFontAttributeName:UIFont(name: "HelveticaNeue-Bold",size: 15.0)!])
alert.setValue(messageMutableString, forKey: "attributedMessage")
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)
if Reachability.isConnectedToNetwork() == true {
var postString = GlobalVariable.globalIpAdress
postString.append("&userid=")
postString.append(userId.text!)
postString.append("&password=")
postString.append(password.text!)
postString.append("&parola=")
let urlString = postString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlFragmentAllowed)
var request = URLRequest(url: URL(string:urlString!)!)
request.httpMethod = "POST"
request.timeoutInterval=10
message="Request timed out"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
DispatchQueue.main.async {
self.dismiss(animated: false, completion: nil)
}
guard let data = data, error == nil else {
print("error=\(String(describing: error))")
DispatchQueue.main.async {
let alert = UIAlertView(title: "Uyarı!", message: self.message, delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
return;
}
if let json = (try? JSONSerialization.jsonObject(with: data, options: [])) as? NSDictionary
{
print(json)
if (json["error"] as? String) != nil {}
if let messages = json["messages"] as? NSArray{
for item in messages {
if let description = item as? AnyObject {
if let text = description["text"] as? String {
self.message = text
}
}
}
}
if let tokenTemp = json["token"] as? String {
self.success=true
GlobalVariable.globalToken = tokenTemp
}
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
DispatchQueue.main.async {
if(self.success == true){
self.performSegue(withIdentifier: "secondVC", sender: self)
} else {
let alert = UIAlertView(title: "Warning!", message: self.message, delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
}
}
task.resume()
}
else{
print("Internet connection FAILED")
let alert = UIAlertView(title: "No Internet Connection", message: "Make sure your device is connected to the internet.", delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
First of all, I am adding indicator view for login screen and then, as soon as token came my Bool success variable is becoming true and I am dismissing the activity indicator then it needs to be gone next screen but it is not working right now and also I am getting following error.
Warning: Attempt to present UITabBarController on UIAlertController: whose view is not in the window hierarchy!
What could be the reason where am I doing wrong?
I think the error itself explains the issue here:
Attempt to present UITabBarController on UIAlertController: whose view is not in the window hierarchy!
As you are presenting the UIAlertController in this line of code :
present(alert, animated: true, completion: nil)
but you are not dismissing it and trying to performSegue on UIAlertController:
self.performSegue(withIdentifier: "secondVC", sender: self)
Dismiss the UIAlertController whenever you present it.
Refer this :
How to programmatically dismiss UIAlertController without any buttons?

Swift 3 send json request I want to use this function so I have difficulties to understand

I found this function to send JSon request and receive the answer
func sendRequest(urlString: String, method: String, completion: #escaping (_ dictionary: NSDictionary?, _ error: Error?) -> Void) {
DispatchQueue.global(qos: .background).async {
var request = URLRequest(url: URL(string:urlString)!)
request.httpMethod = method
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(error)")
completion(nil, error)
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
// make error here and then
completion(nil, error)
return
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(responseString)")
DispatchQueue.main.async {
do {
let jsonDictionary:NSDictionary = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] as NSDictionary
completion(jsonDictionary, nil)
} catch {
completion(nil, error)
}
}
}
task.resume()
}
}
I need to understand how to call this function correctly. I know urlString and method parameters so the completion and how to return the answer to use it after calling this function.

swift tableview displays json data very slow

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
}
}

Error in JSON downloaded data as NSDictionary in Swift

#IBOutlet weak var weather: UILabel!
#IBOutlet weak var city: UITextField!
#IBAction func button(sender: AnyObject) {
let urlpath = "api.worldweatheronline.com/free/v2/weather.ashx?q=\(city.text)&format=json&num_of_days=5&key=c7fc4c9444ae2ddcee02a0893d5f0"
let url = NSURL(string: urlpath)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
self.weather.text="error"
}else{
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
println(jsonResult)
}
})
task.resume()
}
I receive errors in the console when running the application. I am correctly serializing the data I believe but, I can not get the JSON serialized data to show up in an NSDictionary. I have tried to print the Dictionary to the console and it still just shows up as error. Please help me understand whats wrong here.
Try some thing like this.
func fetchWeatherData(latLong: String, completion: WeatherDataCompletionBlock) {
let baseUrl = NSURL(string: "http://api.worldweatheronline.com/free/v2/weather.ashx?q=\(city.text)&format=json&num_of_days=5&key=c7fc4c9444ae2ddcee02a0893d5f0")
let request = NSURLRequest(URL: baseUrl!)
println(request)
let task = session.dataTaskWithRequest(request) {[unowned self] data, response, error in
if error == nil {
var jsonError: NSError?
if (jsonError == nil) {
let weatherDictionary = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.AllowFragments, error: &jsonError) as NSDictionary
let data = WeatherData(weatherDictionary: weatherDictionary)
completion(data: data, error: nil)
} else {
completion(data: nil, error: jsonError)
}
} else {
completion(data: nil, error: error)
}
}
task.resume()
}

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

As you can see, I'm receiving a JSON file, parsing it using SwiftyJSON, and trying to return totalTime, but it won't let me. How do I do this?
func googleDuration(origin: String, destination: String) -> Int{
// 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, 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)
}
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);
}
}
})
task.resume();
}
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
}
}
Another example:
class func getExchangeRate(#baseCurrency: String, foreignCurrency:String, completion: ((result:Double?) -> Void)!){
let baseURL = kAPIEndPoint
let query = String(baseCurrency)+"_"+String(foreignCurrency)
var finalExchangeRate = 0.0
if let url = NSURL(string: baseURL + query) {
NSURLSession.sharedSession().dataTaskWithURL(url) { data, response, error in
if ((data) != nil) {
let jsonDictionary:NSDictionary = NSJSONSerialization.JSONObjectWithData(data!, options: nil, error: nil) as NSDictionary
if let results = jsonDictionary["results"] as? NSDictionary{
if let queryResults = results[query] as? NSDictionary{
if let exchangeRate = queryResults["val"] as? Double{
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
dispatch_async(dispatch_get_main_queue()) {
completion(result: exchangeRate)
}
}
}
}
}
}
else {
completion(result: nil)
}
}.resume()
}
}
Call:
Currency.getExchangeRate(baseCurrency: "USD", foreignCurrency: "EUR") { (result) -> Void in
if let exchangeValue = result {
print(exchangeValue)
}
}
Another example:
func getJason(url: NSURL, completionHandler: (String?, NSError?) -> Void ) -> NSURLSessionTask {
var finalData: String!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in
if error != nil{
completionHandler(nil, error)
return
}
else{
if let urlContent = data{
do{
let jsonData = try NSJSONSerialization.JSONObjectWithData(urlContent, options: NSJSONReadingOptions.MutableContainers)
if let ip = jsonData["ip"]{
finalData = ip as? String
completionHandler(finalData, nil)
return
}
}catch{
print("EMPTY")
}
}
}
}
task.resume()
return task
}
Then i called it in the viewDidLoad
getJason(url) { (ipAddress, error) -> Void in
if error != nil{
print(error)
}
else{
if let ip = ipAddress{ //To get rid of optional
self.ipLabelDisplay.text = "Your Ip Address is: \(ip)"
}
}
}