Simon
Simon

Reputation: 571

Parsing JSON into tableview

I am receiving a JSON file from a remote server and I can display the result in a label. The JSON data is working fine when I call function processJSONData() and the tableview works fine with a simple array. How can I incorporate both to display the result from the JSON file in the tableview? Kindly look at the code below and edit. Many thanks:

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var countryLabel: UILabel!
    @IBOutlet weak var capitalLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        //processJSONData()
                  self.myTableView.registerClass(UITableViewCell.self,forCellReuseIdentifier: "cell")
        self.myTableView.dataSource = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func processJSONData(){
        let urlPath = "http://dubaisinan.host22.com/service1.php"
        let url : NSURL = NSURL(string: urlPath)!
        let session = NSURLSession.sharedSession()

        let task = session.dataTaskWithURL(url,completionHandler: {(data, respose, error) -> Void in
            if error != nil {
                println(error)
            }
            else {
                    self.abc(data)
            }
        })
        task.resume()
    }


    func abc(data:NSData)
    {
        var parseError: NSError?

        let result:AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &parseError);

        if(parseError == nil){
            if let dictResult = result as? NSArray{

                dispatch_async(dispatch_get_main_queue()) {
                self.countryLabel.text = dictResult[2]["Capital"] as? String
                }
            }
        }
    }

    @IBOutlet weak var myTableView: UITableView!

    var items = ["One","Two", "Three","Four"]

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }


    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell:UITableViewCell = self.myTableView

        .dequeueReusableCellWithIdentifier("cell") as UITableViewCell

        cell.textLabel?.text = self.items[indexPath.row]
        return cell
    }
}

Upvotes: 2

Views: 231

Answers (3)

Yariv Nissim
Yariv Nissim

Reputation: 13343

You should update your items property in abc method call and then refresh the table:

func abc(data: NSData) {
   // Do something with data
   items = .. // processed data
}

var items: [String]? {
    didSet {
        NSOperationQueue.mainQueue.addOperationWithBlock {
            self.tableView.reloadData()
        }
    }
}

Upvotes: 1

Eugene Braginets
Eugene Braginets

Reputation: 856

I don't see you assign your parsing result to global "items" and reload tableview with new data anywhere.

could be done here

if let dictResult = result as? NSArray{
    self.items = dictResult
    self.myTableView.reloadData()

///the rest of the code
            }

Upvotes: 2

stone
stone

Reputation: 8662

You have to save the JSON data into a class-level variable, which you will define outside of any function, similar to how you defined "items". Assuming you have a list of countries with the capital of each, this might look like so:

var countryAndCapitalData = [(country: String, capital: String)]()

This could be improved by first defining a struct to contain your data:

struct CountryInfo
{
    name: String
    capital: String
    init(name:String, capital:String)
    {
        self.name = name
        self.capital = capital
    }
}

which lets you define your data array as an array of CountryInfo:

var countryAndCapitalData = [CountryInfo]()

Then in your "abc" function (which I insist you rename to something like processCountryData), store the pairs of country name + capital name strings in countryAndCapitalData. For example:

countryAndCapitalData.append(CountryInfo(countryName, capitalName))

Use a For loop to loop through values in dictResult. Creating countryName and capitalName depends on the structure of your JSON, but from your example it might look like this:

for countryDictionary in dictResult[2]
{
    if let countryName = countryDictionary["country"], let capitalName = countryDictionary["capital"]
    {
        countryAndCapitalData.append(CountryInfo(countryName, capitalName))
    }
}

Then in tableView.cellForRowAtIndexPath, populate the cell label(s) with countryAndCapitalData[indexPath.row].name and countryAndCapitalData[indexPath.row].capital.

And finally, be sure to reload the table after the loop (thanks Eugene):

dispatch_async(dispatch_get_main_queue()) {
    self.myTableView.reloadData()
}

Apologies for any compilation errors, as I'm typing this from a Windows machine.

Upvotes: 1

Related Questions