Access data from NSDictionary - ios

I'm trying to get data from an NSDictionary in Swift but I'm not able to do this.
Here is the code
let urlPath = "http://ws-report.goocity.it/Stats/json/GetReport"
let url: NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
var result: NSDictionary
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
if err != nil {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
else{
//var arr : NSArray = jsonResult.valueForKey("Stats") as NSArray
//var cash: String? = jsonResult.valueForKey("Cash") as? NSString
let stats = jsonResult["Stats"]! as [[String : AnyObject]]
}
})
task.resume()
You can see the JSON clicking on the urlPath.
I still receive the following error on the let stats = ...
Thread 5: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
I've just checked out few other posts here on stackoverflow and anywhere, but no answer is good for my issue.
I need to get all JSON field values in many variables (like cash, lastUpdate, totalPartners, etc).

Your json is not an array of Dictionaries, it is just a Dictionary.
Change [[String: AnyObject]] to [String: AnyObject] and it will work.

Related

Unwrapping Yahoo API with Swift

I'm trying to get the Price and Change data from Yahoo finance API in JSON format. Apple Stock API
However there are some issues when unwrapping the data. The program shows issue when executing for jsonObjectString in resultArray!. I suspect it found no data, because the error during debug was fatal error: unexpectedly found nil while unwrapping an Optional value
func GetPrice(){
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: "https://query.yahooapis.com/v1/public/yql?q=select%20price%2C%20change%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes.csv%3Fs%3DA17U.SI%26f%3Dsl1d1t1c1ohgv%26e%3D.csv'%20and%20columns%3D'symbol%2Cprice%2Cdate%2Ctime%2Cchange%2Ccol1%2Chigh%2Clow%2Ccol2'&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys")!)
request.HTTPMethod = "GET"
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let data = data{
do{
let resultJSON = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions())
let resultArray = resultJSON as? NSArray
for jsonObjectString in resultArray!{
let price = jsonObjectString["price"] as! String
let change = jsonObjectString["change"] as! String
self.priceList.append(PriceTable(stockCode: self.blueChipList[self.index].stockName, price: price, change: change))
}
dispatch_async(dispatch_get_main_queue(), {self.tableView.reloadData()})
}catch _{
print("Received not-well-formatted JSON")
}
}
if let response = response {
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
resultJSON is dictionary, which is why it is returning nil when you cast it to NSArray.
if you want to get the value for price and change, try this instead.
let resultDict = resultJSON as? NSDictionary
let queryDict = resultDict["query"]
let resultsDict = queryDict["results"]
let rowDict = resultsDict["row"]
let price = rowDict["price"] as! String
let change = rowDict["change"] as! String

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

Create variables from JSON array

I'm trying hard to learn IOS development.
I have followed this guide and successfully managed to create a working quiz game. The last couple of days I have been trying to connect the game to an external database. Finally after many hours I'm able to read from MYSQL using JSON parsing.
Right now Im struggling with a way to convert the json array into a normal array.
My current hardcoded questions look like this:
let questionOne = questionTemplate("the first question?", answerOne: "a answer", answerTwo: "a second answer", answerThree: "a third aswer", answerFour: "tast possible answer", correctAnswer: 2)
Then they are added to an array
spormslaArray = [questionOne, questionTwo, questionThree, questionFour, questionFive, questionSix,questionSeven]
Then im doing some more loading of answers and questions before i add them to the GUI based on an array counter from the first to the last question.
func questionTemplate(question:String, answerOne:String, answerTwo:String, answerThree:String, answerFour:String, correctAnswer:Int) -> NSArray {
//Set the question
var quizQuestion = question
//set the answers and the right answer
var firstAnswer = answerOne
var secondAnswer = answerTwo
var thirdAnswer = answerThree
var fourthAnswer = answerFour
var rightAnswer = correctAnswer
var gjennverendeSporsmal = 1
//Add all the questions and answers to an array
let questionAnswerArray = [question, firstAnswer, secondAnswer, thirdAnswer, fourthAnswer, rightAnswer]
return questionAnswerArray
}
I now want to add questions from my database into spormslaArray.I got questions loaded into xcode using this code:
func lasteJson(){
let urlPath = "http://universellutvikling.no/utvikling/json.php"
let url: NSURL = NSURL(string: urlPath)!
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?
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)")
}
let json = JSON(jsonResult)
let count: Int? = json["data"].array?.count
// println("found \(count!) challenges")
//Im just setting a hardcoded number, it will be based on the array when I have figured that out
var tall = 7
let ct = count
for index in 0...tall-1 {
println(json["data"][index] )
//DEtte printer ut induviduelt
/*
if let questionId = json["data"][index]["id"].string {
println(questionId)
}
if let spm1 = json["data"][index]["answerOne"].string {
println(spm1)
}
if let spm2 = json["data"][index]["answerTwo"].string {
println(spm2)
}
if let spm3 = json["data"][index]["answerThree"].string {
println(spm3)
}
if let spm4 = json["data"][index]["answerFour"].string {
println(spm4)
}
if let correctAnswer = json["data"][index]["correctAnswer"].string {
println(correctAnswer)
}
*/
}
//}
})
task.resume()
This is mostly based on this code.
If Im ignoring the fact that Im getting some breakpoints when im running the app, and that nordic characters in my database makes the ios simulator crash; This is the parsing result in the command line:
{
"correctAnswer" : "1",
"id" : "0",
"answerThree" : "aa3",
"answerFour" : "aa4",
"questionTemplate" : "sporsmal",
"answerOne" : "as1",
"answerTwo" : "aa2"
}
//////Finally here is the problem///////
I have tried for hours to make a variable from the json array, into the guestion array.
I want to do something like this:
let questionOne = json["data"][index]["answerOne"].string
and then add them to an array
let questionArray[questionOne, QuestionTwo.. etc]
I have tried for hours without any progress, so my last hope is you guys! :-)
Use this...
To post JSON or to receive JSON (Leave dictionary nil to GET)
///Use completion handler to handle recieved data
func sendJSON(params:Dictionary<String, String>?, toAdressOnServer:String, customCompletionHandler:((parsedData:AnyObject?, statusCode: Int) -> Void)?){
var request = NSMutableURLRequest(URL: NSURL(string: SERVER_NAME + toAdressOnServer)!)
var session = NSURLSession.sharedSession()
var err: NSError?
if (params == nil){
request.HTTPMethod = "GET"
}else{
request.HTTPMethod = "POST"
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params!, options: nil, error: &err)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments , error: &err)
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
customCompletionHandler?(parsedData: json, statusCode: -1)
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON: AnyObject = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
// Use keyword "success" in JSON from server to register successful transmission
let success = parseJSON["success"] as? Int
if (success == nil){
customCompletionHandler?(parsedData: json, statusCode: -2)
}else{
customCompletionHandler?(parsedData: json, statusCode: success!)
}
}
else {
// The json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
customCompletionHandler?(parsedData: json, statusCode: -1)
}
}
})
task.resume()
}
And To decode the JSON in your case the array, but it can have any form.
self.sendJSON(nil, toAdressOnServer: "ADRESS", customCompletionHandler: { (parsedData, statusCode) -> Void in
//check for valid data
if (parsedData != nil){
//Loop through results
for (var x = 0; x < parsedData!.count; x++){
///primary key of the item from the internet
let pk:Int = (parsedData![x] as NSDictionary).objectForKey("pk") as Int
let month = ((parsedData![x] as NSDictionary).objectForKey("fields") as NSDictionary).objectForKey("month")! as String
let quote = ((parsedData![x] as NSDictionary).objectForKey("fields") as NSDictionary).objectForKey("quote")! as String
let quotee = ((parsedData![x] as NSDictionary).objectForKey("fields") as NSDictionary).objectForKey("quotee")! as String
})
This is an example, use parsed data as "json" and use it with the appropriate structure. In this case the JSON was An array of some dictionary with a fields dictionary that has another dictionary with more fields. So you can have any JSON structure.
I Hope this helps!
It seems that you almost have the answer there. I think what you are missing is questionArray.append(... in your loop to build your array. You could also make things easier for yourself if you modified your JSON so that the questions were in an array rather than discrete keys and change your questionTemplate to take an array rather than discrete answers.
Working with what you have however -
func lasteJson(){
let urlPath = "http://universellutvikling.no/utvikling/json.php"
let url: NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
questionsArray=[Question]()
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)
}
else {
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)")
}
else {
let questions=jsonResult["data"] as? [[String:String]]
if (questions != nil) {
for question in questions! {
let answer1=question["answerOne"]!
let answer2=question["answerTwo"]!
let answer3=question["answerThree"]!
let answer4=question["answerFour"]!
let id=question["id"]!
let questionTemplate=question["questionTemplate"]!
let correctAnswer=question["correctAnswer"]!
let newQuestion=Question(questionTemplate, answerOne: answer1, answerTwo:answer2, answerThree: answer3, answerFour: answer4, correctAnswer: correctAnswer)
questionsArray.append(newQuestion)
}
}
}
}
})
task.resume()
}
You don't show your questionTemplate, but I am not sure why/how it returns an array. My code above assumes that there is a class Question and fills in a property questionsArray

Parse Google Calendar JSON in SWIFT

I'm brand new to Swift development. I'm trying to build a basic app which will read a feed from Google Calendar which is returned in JSON.
I am able to use a NSURLConnection.sendAsynchronousRequest call as described in this thread: Make REST API call in Swift and I get a result of some sorts.
My problem is I am unable to parse the JSON into some meaningful objects from which I can create a list of upcoming events.
My code this far is:
var url : String = "some url"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if (jsonResult != nil){
// No idea how to parse this object as it seems to be a NSDictionary but battling to interact with it.
}
else
{
}
})
Any help would be greatly appreciated.
If you put a breakpoint after
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
then you'll be able to see the dictionary key/value pairs. I copied/pasted your code and see this:
You can access the values by using jsonResult.objectForKey("keyName"). I'm also going to downcast using as DataType.
Example)
let encoding = jsonResult.objectForKey("encoding") as String
let version = jsonResult.objectForKey("version") as String
let feed = jsonResult.objectForKey("feed") as NSDictionary

Resources