1

I'm just getting to grips with iOS development and Xcode altogether, and I'm learning it with Swift 2. I'm trying to get some JSON data from a URL, split it up into a swift Array, and display it in a TableView. I have managed to split the JSON data into an Array, but I'm having trouble reloading the table's data to get it to display this. Here's the code I have:

//
//  ViewController.swift
//  Table JSON
//
//  Created by James Allison on 06/11/2015.
//  Copyright © 2015 James Allison. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    var cellContent = ["this should be replaced","something","something else"]

    @IBOutlet weak var table: UITableView!
    override func viewDidLoad() {
        super.viewDidLoad()

        // construct url
        let url = NSURL(string: "http://127.0.0.1:8888/json.php")!

        let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in
            // the following will happen when the task is complete
            if let urlContent = data {

                var webContent =  NSString(data: urlContent, encoding: NSUTF8StringEncoding)

                // remove []
                webContent = webContent?.stringByReplacingOccurrencesOfString("[", withString: "")
                webContent = webContent?.stringByReplacingOccurrencesOfString("]", withString: "")

                // split by commas
                var webContentArr = webContent?.componentsSeparatedByString(",")

                var temp = ""
                // remove quote marks
                for var i = 0; i < webContentArr!.count; i++ {
                    temp = webContentArr![i]
                    temp = temp.stringByReplacingOccurrencesOfString("\"", withString: "")
                    webContentArr![i] = temp
                }

                print(webContentArr!)
                self.cellContent = webContentArr! as! Array
                self.table.reloadData()

            }
            else {
                // something failed
                print("Error: invalid URL or something.")
            }
        }
        task.resume()

    }

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

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
        cell.textLabel?.text = cellContent[indexPath.row]

        return cell
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

At the moment when I run it the table displays the original cellContent variable, but not the new one. No errors are produced, and the array is printed okay.

Edit: Thanks Joshua for your answer. I ended up using the following code to solve my issue:

dispatch_async(dispatch_get_main_queue(), { () -> Void in
     self.cellContent = webContentArr! as! Array
     self.table.reloadData()
})

1 Answer 1

1

At a guess, your "will happen when the task is complete" code is being run on some thread/queue other than main, which does not play well with UI updates. Anything that touches the UI must be done on the main queue.

You should adjust your code so that both the replacement of cellContent and the call to your table view to reloadData() are scheduled on the main queue after you're finished processing everything. To do so, wrap both the above-mentioned calls in an async dispatch sent to the main queue:

dispatch_async(dispatch_get_main_queue(), ^{

    self.cellContent = webContentArr! as! Array
    self.table.reloadData()

});

This will ensure the cellContent array isn't being modified "behind the table view's back" while it's updating the UI on the main queue (bad!) and that the table view doesn't try updating again until it's done with any ongoing updates.

I hope this helps.

Sign up to request clarification or add additional context in comments.

1 Comment

You're welcome. :-) It's a very important topic to be aware of, especially when interacting with any UI objects. Any time you pass a closure (a block of code that's run later) that needs to update the UI when it's run, remember to "jump back" to the main queue both to update any collections (like your cellContent array) or other properties that the UI needs, and to update the UI itself.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.