Mark Gong-Guy Mark Gong-Guy - 5 months ago 9
Swift Question

Trouble returning JSON data with custom datatype using Swift

I'm having trouble using this code that essentially downloads JSON data and parses it, to return the returnInfo. When I print the info it is intact however when it is returned the struct defaults are returned. Not sure what I"m doing wrong any help would be highly appreciated!

Let me know if you need any additional information and I would be happy to provide it.

import Foundation

struct stockData {
var name: String = ""
var askPrice: String = ""
var percentageChange: String = ""
}


class stockinfo {


init () {

}


func getInfo (stock: String) -> stockData{

let stockSymbol = stock // Sets stock symbol
var returnInfo = stockData()

// Configuration for request and starts the connection

let requestURL: NSURL = NSURL(string: "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22" + stockSymbol + "%22)&env=store://datatables.org/alltableswithkeys&format=json")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in

let httpResponse = response as! NSHTTPURLResponse
let statusCode = httpResponse.statusCode

if (statusCode == 200) {
print("JSON File Downloaded Successfully")

do{

let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)

// Parses out the JSON Query into data to be assigned to a variable and returned

let query: NSDictionary = json["query"] as! NSDictionary
let results: NSDictionary = query["results"] as! NSDictionary
let quote: NSDictionary = results["quote"] as! NSDictionary
let companyName: String = quote["Name"] as! String
let askPrice: String = quote["Ask"] as! String
let percentageChange: String = quote["ChangeinPercent"] as! String


// Places JSON data into return struct
print(companyName)
print(askPrice)
print(percentageChange)

returnInfo.name = companyName
returnInfo.askPrice = askPrice
returnInfo.percentageChange = percentageChange

} catch {
print("Error with Json: \(error)")
}

}
}

task.resume()
return returnInfo
}
}

Answer

You need a completion handler to wait for the async call dataTaskWithRequest to complete. Modify your code like:

func getInfo (stock: String, completion: (cName: String, price: String, percentChange: String) -> ()) -> stockData{

//your code
let companyName: String = quote["Name"] as! String
                let askPrice: String = quote["Ask"] as! String
                let percentageChange: String = quote["ChangeinPercent"] as! String


                // Places JSON data into return struct
                print(companyName)
                print(askPrice)
                print(percentageChange)
             completion(cName: companyName, price: askPrice, percentChange: percentageChange)

}
//your code

And then whenever you want to call this, essentially after a button press or if you prefer in viewDidLoad do this:

getInfo("your string") {(name, price, change) in
///use the three values how you want.
}