I am trying to get data from my api in JSON with SwiftyJSON, but I get this error from server:
{"Message":"An error has occurred."}
I want to handle it but I get an error in this part when I want to request json
I just want my do nothing when server respond this result
func parsing(){
var URLString = server + "api/XXXXXX" + String(nextpage) + "&pagesize=10"
print(URLString)
guard let
URLString1 = URLString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
else {fatalError()}
let url = NSURL(string: URLString1)!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, innerError) in
if let data = data where innerError == nil {
let jsonData1 = NSData(contentsOfURL: url) as NSData!
let readableJson = JSON(data: jsonData1, options: NSJSONReadingOptions.MutableContainers, error: nil)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.nrows = readableJson.count
for var i = 0 ; i < self.nrows ; i++ {
var json = readableJson[i]
let desc = json["Name"].string as String!
let iddesc = json["Id"].intValue//.string as String!
let groupName = json["Group_Name"].string as String!
let price1 = json["Price"].string as String!
}
}
}
}
task.resume()
}
Related
For some reason the JSON object from parsing doesnt update after network calls to and api we built. I check the endpoint and now for a fact it updates right away. I have a timer being called every 10 sec to make the call but the parsed json doesnt update until after a minute or so. I have tried putting it on the main thread and that still doesnt work. Here is my code:
#objc func getLaunches() {
let simulator = UserDefaults.standard.string(forKey: self.launchSimulator)
if(simulator == self.password){
print("they are the same")
}
guard let launchUrl = URL(string: launchesURL) else {
return
}
let request = URLRequest(url: launchUrl)
DispatchQueue.main.async { [weak self] in
let task = URLSession.shared.dataTask(with: request, completionHandler: {
(data, response, error) -> Void in
if let error = error {
print(error)
return
}
// Parse JSON data
if let data = data {
self?.launches.removeAll()
self?.launches = (self!.parseJsonData(data: data))
let nextlaunch = self?.launches[0]
// Reload table view
self?.hours = nextlaunch?.time
self?.yearMonth = nextlaunch?.date
var fulltime = self?.yearMonth
fulltime!.insert("-", at: fulltime!.index(fulltime!.startIndex, offsetBy: 4))
fulltime!.insert("-", at: fulltime!.index(fulltime!.startIndex, offsetBy: 7))
fulltime = fulltime! + " "
fulltime = fulltime! + self!.hours
let fullFormatter = DateFormatter()
fullFormatter.dateFormat = "YYYY-MM-dd HH:mm"
fullFormatter.timeZone = TimeZone(abbreviation: "EST")
self?.launchDate = fullFormatter.date(from: fulltime!)
self?.getCountdown()
}
})
task.resume()
}
}
//parse launch info from json to dictionary into launches object
func parseJsonData(data: Data) -> [NextLaunch] {
var launches = [NextLaunch]()
do {
let jsonResult = try JSONSerialization.jsonObject(with: data, options:
JSONSerialization.ReadingOptions.allowFragments) as? NSDictionary
let jsonLaunches = jsonResult?["launches"] as! [NSDictionary]
for jsonLaunch in jsonLaunches {
let launch = NextLaunch()
launch.date = jsonLaunch["date"] as! String
launch.time = jsonLaunch["time"] as! String
if(launch.time == ""){
launch.time = "00:00"
}
launch.mission = jsonLaunch["mission"] as! String
launch.launchpad = jsonLaunch["launch_pad"] as! String
launch.image = jsonLaunch["image"] as! String
launch.delay = jsonLaunch["delayed"] as! String
//show delay image if it is delayed
if(launch.delay == "1"){
self.delayed()
}else{
self.notDelayed()
}
launches.append(launch)
}
} catch {
print(error)
}
return launches
}
You need
DispatchQueue.main.async {
self?.getCountdown()
}
As the response of URLSession.shared.dataTask(with: occurs in a background thread
I am trying to add values from what
was printed in the json shown by my code
to specific arrays. For example I want
the lat / lng /name from the JSon file and
add it to an array. How would I go about doing this
? I am new to swift and would appreciate the help.
My Json code is in the comments! Thanks
func getBurritosInArea() {
let keyword:String = "burrito"
let urlString =
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=\(latitude),\(longitude)&&fields=formatted_address,name,rating&radius=1500&type=restaurant&keyword=(\apikey)"
guard let request = URL(string:urlString) else { return }
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil,
let json = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers),
let results = json as? [String: Any] else { //error handling
return
}
if let placeResults = results["results"] as? [[String: Any]]{
for placeResult in results{
print(placeResult)
}
}
}
}
}
json code:
viewport = {
northeast = {
lat = "40.74642527989272";
lng = "-73.97449797010727"; };
southwest = {
lat = "40.74372562010728";
lng = "-73.97719762989271"; };
};
};
icon = "maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png"; id = c884c332c5cc1578d0c1d4d7f4d4ad451358c9e6;
name = "Baby Bo's Cantina"; "opening_hours" = { "open_now" = 1; };
Hi Please try below code,
First Create an Array Named aryDict,
func getBurritosInArea()
{
guard let url = URL(string: "your url") else {return}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return }
do{
//here dataResponse received from a network request
let jsonResponse = try JSONSerialization.jsonObject(with:
dataResponse, options: []) as? NSArray
// print(jsonResponse?.value(forKey: STR_NAME) as Any )
let array = NSArray.init(array: jsonResponse ?? [])
var aryDict = NSMutableArray.init(array: array)
// self.tblView.reloadData()
print(aryDict)
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}
Guys I need assistance on swift 4.0
i have a simple function that calls a json and fills those vars with values.
self.getDataFromServer()
after 'self.getDataFromServer()' this will fill in the arrays with retrieved data. This was working great on the previous version of swift (swift 3).
This is the code after the self.getDataFromServer() and getting index out of range, because data isn't populated (PS: This was working on swift 3.0)
var totalAmount = [String]()
var remainingAmount = [String]()
self.getDataFromServer()
let newTotal = Int(totalAmount[0])! + Int(remainingAmount[0])!
let newRemaining = String(newTotal)
updateDailyData(newRemainingAmount: newRemaining, id: userID[0])
I'm getting error on 'newTotal' saying index out of range. Please Help.
I noticed that on swift 4, I'm facing this issue whenever i'm calling JSON.
The JSON Function is as below:
func getDataFromServer() {
let dateOfToday = Date()
let strDateOfToday = convertToString(myDate: dateOfToday)
let postString = "ANYTHING HERE";
let myUrl = URL(string: "ANYTHING HERE")
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"// Compose a query string
request.httpBody = postString.data(using: String.Encoding.utf8);
//Start the task
let task = URLSession.shared.dataTask(with: request) {
(data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
print("error=\(String(describing: error))")
return
}
let values = try! JSONSerialization.jsonObject(with: data! as Data, options: JSONSerialization.ReadingOptions.allowFragments) as! NSArray
let success = ((values.value(forKey: "success") as? [String])! as NSArray) as! [String]
if (success[0] == "1")
{
self.totalAmount = ((values.value(forKey: "totalAmount") as? [String])! as NSArray) as! [String]
self.remainingAmount = ((values.value(forKey: "remainingAmount") as? [String])! as NSArray) as! [String]
}
}
//Let's convert response sent from a server side script to a NSDictionary object:
task.resume()
}
Here is your perfect working solution using Closure
Swift 4
self.getDataFromServer { (arrTotalAmount, arrRemainingAmount) in
if arrTotalAmount.count > 0, arrRemainingAmount.count > 0 {
// Your code here
let newTotal = Int(totalAmount[0])! + Int(remainingAmount[0])!
let newRemaining = String(newTotal)
updateDailyData(newRemainingAmount: newRemaining, id: userID[0])
}
}
func getDataFromServer(completion: #escaping (_ arrTotalAmount: [String], _ arrRemainingAmount: [String]) -> Void) {
let dateOfToday = Date()
let strDateOfToday = convertToString(myDate: dateOfToday)
let postString = "ANYTHING HERE";
let myUrl = URL(string: "ANYTHING HERE")
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"// Compose a query string
request.httpBody = postString.data(using: String.Encoding.utf8);
//Start the task
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
print("error=\(String(describing: error))")
return
}
let values = try! JSONSerialization.jsonObject(with: data! as Data, options: JSONSerialization.ReadingOptions.allowFragments) as! NSArray
let success = ((values.value(forKey: "success") as? [String])! as NSArray) as! [String]
if (success[0] == "1")
{
let totalAmount = ((values.value(forKey: "totalAmount") as? [String])! as NSArray) as! [String]
let remaininAmount = ((values.value(forKey: "remainingAmount") as? [String])! as NSArray) as! [String]
completion(totalAmount, remaininAmount)
}
}
//Let's convert response sent from a server side script to a NSDictionary object:
task.resume()
}
I can't really imagine this working in Swift 3, since the effects of your getDataFromServer function are asynchronous. More precisely, the function returns before the code inside the dataTask is executed.
Try something like this to execute code on the caller side after the dataTask has succeeded:
func getDataFromServer(onDone: () -> Void) {
...
let task = URLSession.shared.dataTask(with: request) { ... in
...
onDone()
}
task.resume()
}
And to call it:
var totalAmount = [String]()
var remainingAmount = [String]()
self.getDataFromServer {
let newTotal = Int(totalAmount[0])! + Int(remainingAmount[0])!
let newRemaining = String(newTotal)
updateDailyData(newRemainingAmount: newRemaining, id: userID[0])
}
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()
I'd like to get token as String type, however the following code returns error as " "String" is not convertible to "Void" ".
Could you tell me what is the problem?
In order to parse JSON, I used SwiftyJSON
func authentication() -> String {
let request = NSMutableURLRequest(URL: NSURL(string: "https://~~~/v2/authenticate/api")!)
request.HTTPMethod = "POST"
var loginID = "my_ID"
var apiKey = "my_APIKEY"
var postString:NSString = "login_id=\(loginID)&api_key=\(apiKey)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
println("error=\(error)")
return
}
println("response = \(response)")
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("responseString = \(responseString)")
let json = JSON(data:data)
if let token = json["auth_token"].stringValue{
println("\(token)")
return token ///Error Here
}
}
task.resume()
}
※Edited Jan6th 7:50(GMP+9hr)
I edited as following, however I got error as ""Use of unresolved identifier "tokenString".
Please tell me how to solve the problem.
func authentication() -> String {
let request = NSMutableURLRequest(URL: NSURL(string: "https://~~~/v2/authenticate/api")!)
request.HTTPMethod = "POST"
var loginID = "my_ID"
var apiKey = "my_APIKEY"
var postString:NSString = "login_id=\(loginID)&api_key=\(apiKey)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
println("error=\(error)")
return
}
println("response = \(response)")
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("responseString = \(responseString)")
let json = JSON(data:data)
if let token = json["auth_token"].stringValue{
println("\(token)")
tokenString = self.didReceiveAuthToken(token)///Edited
}
}
task.resume()
return tokenString
}
func didReceiveAuthToken(token : String) ->String{
return token
}
The dataTaskWithRequest closure takes a return type of void. Your method that returns a string ends immediately after task.resume() is executed and does not return anything.
Your basic problem is that you're applying synchronous thinking to an asynchronous task. One easy suggestion is to have authentication() return void (ie, nothing), and then make a separate method like didReceiveAuthToken(token : String) that is called by your completion handler when the token is received.