YichenBman
YichenBman

Reputation: 5651

Create API Class to handle JSON Data Swift

I'm extremely new to handling JSON Data in Swift, and almost just as new to Swift. In a Playground I wrote a whole bunch of code that parsed JSON Data out.

However I realized I don't want to copy and paste this code into every view controller that uses only some of the data. I want to create a custom class that handles the json data.

Here is a bit of my code:

var status: String!
var message: String!
var code: Int!
var dataArray: [NSDictionary]!
var responseCode: String!


var url: NSURL!
var session: NSURLSession!



url = NSURL(string: "http://thisappgonnabecoool.json")

session = NSURLSession.sharedSession()


let task = session.dataTaskWithURL(url!, completionHandler: { data, response, error -> Void in
if (error != nil) {
    // println(error)

} else {
    let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary




    status = jsonResult["status"] as! String
    message = jsonResult["message"] as! String
    code = jsonResult["code"] as! Int
    dataArray = jsonResult["data"] as! [NSDictionary]


}

})
task.resume()

I then attempted to create a class like this:

class JsonClass {

var status: String!
var message: String!
var code: Int!
var dataArray: [NSDictionary]!
var responseCode: String!


var url: NSURL!
var session: NSURLSession!


init() {
 url = NSURL(string: "http://thisappgonnabecoool.json")

session = NSURLSession.sharedSession()


let task = session.dataTaskWithURL(url!, completionHandler: { data, response, error -> Void in
if (error != nil) {
    // println(error)

} else {
    let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary




    status = jsonResult["status"] as! String
    message = jsonResult["message"] as! String
    code = jsonResult["code"] as! Int
    dataArray = jsonResult["data"] as! [NSDictionary]


}

})
task.resume()


}

I thought that within a new class I would be able to do something like this:

let jsonAPI = JsonClass()
println(jsonAPI.status)
println(jsonAPI.message)

etc...

However, any attempt to access an instance of the JsonClass results in every JsonClass property having a value of nil.

What are my next steps to accessing this data using instances of this class?

Upvotes: 3

Views: 1758

Answers (2)

YichenBman
YichenBman

Reputation: 5651

Much thanks for everyone. I'm posting a sample of my API as the answer since it is the most complete answer.

As stated earlier, my issue wasn't with parsing, it had to do with the fact that dataTaskWithURL was called after the call to init() returns. I've solved the issue by adding a completion handler to the method I use to download the data.

class JsonAPI {


var status: String!
var message: String!
var code: Int!
var dataArray: [NSDictionary]!
var responseCode: String!

var url: NSURL!
var session: NSURLSession!


func getData(completionHandler: ((NSArray!, NSError!) -> Void)!) -> Void {


    url = NSURL(string: "myapp.json")

    session = NSURLSession.sharedSession()


    let task = session.dataTaskWithURL(url!, completionHandler: { data, response, error -> Void in
        if (error != nil) {
            // println(error)
//If there is an error, return nil for the data, and error for the error
            return completionHandler(nil, error)

        } else {
            let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary

            self.status = jsonResult["status"] as! String
            self.message = jsonResult["message"] as! String
            self.code = jsonResult["code"] as! Int
            self.dataArray = jsonResult["data"] as! [NSDictionary]

        }
//If there aren't errors, return whatever you parsed as the data, and nil for error
        return completionHandler(self.dataArray, nil)
    })
    task.resume()

}


}

From separate classes I call the getData() method like this:

var api = JsonAPI()

api.getData({data, error -> Void in
        if (data != nil) {
            self.newDataArray = data


        } else {
            println("api.getData failed")
            println(error)
        }
    })

Upvotes: 0

gnasher729
gnasher729

Reputation: 52592

Your problem has nothing at all to do with parsing JSON. Your problem is that you have an asynchronous call, and the asynchronous call isn't finished by the time you look at the results.

The completion handler of dataTaskWihURL can be called half a second, five seconds, or sixty seconds after the call to init () returns.

Upvotes: 4

Related Questions