Reputation: 7537
I am working on an app that displays the live Bitcoin price. I am using 2 APIs to do this - one plaintext, and one JSON. I am having a bit of trouble with the JSON API.
Here's a bit of my Swift code
func BTCFallback(){
var string2 = currencySelector.currentTitle
var url = NSURL(string:"https://bitpay.com/api/rates/" + (string2)!)
var request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:fallback)
var data = NSData(contentsOfURL:url);
let value = NSString(string: USD.text).doubleValue / NSString(data:data, encoding:NSUTF8StringEncoding).doubleValue
// Define JSON string
var JSONString = "\(data)"
// Get NSData using string
if let JSONData = JSONString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
// Parse JSONData into JSON object
var parsingError: NSError?
if let JSONObject = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &parsingError) as? [String: AnyObject] {
// If the parsing was successful grab the rate object
var rateObject: AnyObject? = JSONObject["rate"]
// Make sure the rate object is the expected type
if let rate = rateObject as? Float {
println("rate is \(rate)")
BTC.text = "\(rate)"
}
} else {
// There was an error parsing the JSON data
println("Error parsing JSON: \(parsingError)")
BTC.text = "err1"
}
}
}
In the above code, currencySelector.currentTitle is equal to an ISO currency code, for instance USD. BTC.text is a UI element.
The expected behavior is that the code will set the counterpart of "rate" as the text of BTC.text. In case this helps, the API returns something like {"code":"USD","name":"US Dollar","rate":376.71}. I would want, using the above example, to have BTC.text set to 376.71
Here's what's happening: the consoe gives the error
Error parsing JSON: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x16eb0f60 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.})
What am I doing wrong? Thanks in advance!
Upvotes: 1
Views: 5084
Reputation: 112857
It is all a matter of handling the returned data and de-serialization.
Here is example code, note that the handling of Optionals should be better, this is just to demonstrate the basic code. For example purposes I used a simple synchronous web call.:
var url: NSURL! = NSURL(string:"https://bitpay.com/api/rates/AUD")
var request = NSURLRequest(URL: url)
var response: NSURLResponse?
var error: NSError?
var data: NSData? = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&error)
println("data: \(data)")
if let data: NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&error) {
println("data: \(data)")
var parsingError: NSError?
if let rateDictionary = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parsingError) as NSDictionary? {
println("rateDictionary: \(rateDictionary)")
// If the parsing was successful grab the rate object
if var rateString: AnyObject = rateDictionary["rate"] {
println("rateString: \(rateString)")
// Make sure the rate object is the expected type
if let rate = rateString.floatValue {
println("rate is \(rate)")
}
}
}
}
Ouput:
data: Optional(7b22636f 6465223a 22415544 222c226e 616d6522 3a224175 73747261 6c69616e 20446f6c 6c617222 2c227261 7465223a 3430372e 39393137 7d) rateDictionary: { code = AUD; name = "Australian Dollar"; rate = "407.9917"; } rateString: 407.9917 rate is 407.992
Upvotes: 3