self.tableView.reloadData() not working in Swift

112,327

Solution 1

You'll need to reload the table on the UI thread via:

//swift 2.3
dispatch_async(dispatch_get_main_queue(), { () -> Void in
    self.tableView.reloadData()
})

//swift 5
DispatchQueue.main.async{
    self.tableView.reloadData()
}

Follow up: An easier alternative to the connection.start() approach is to instead use NSURLConnection.sendAsynchronousRequest(...)

//NSOperationQueue.mainQueue() is the main thread
NSURLConnection.sendAsynchronousRequest(NSURLRequest(URL: url), queue: NSOperationQueue.mainQueue()) { (response, data, error) -> Void in
    //check error
    var jsonError: NSError?
    let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &jsonError)
    //check jsonError
    self.collectionView?.reloadData()
}

This doesn't allow you the flexibility of tracking the bytes though, for example you might want to calculate the progress of the download via bytesDownloaded/bytesNeeded

Solution 2

You have just to enter:

First a IBOutlet:

@IBOutlet var appsTableView : UITableView

Then in a Action func:

self.appsTableView.reloadData()

Solution 3

If your connection is in background thread then you should update UI in main thread like this

self.tblMainTable.performSelectorOnMainThread(Selector("reloadData"), withObject: nil, waitUntilDone: true)

As I have mentioned here

Swift 4:

self.tblMainTable.performSelector(onMainThread: #selector(UICollectionView.reloadData), with: nil, waitUntilDone: true)

Solution 4

In my case the table was updated correctly, but setNeedDisplay() was not called for the image so I mistakenly thought that the data was not reloaded.

Solution 5

Beside the obvious reloadData from UI/Main Thread (whatever Apple calls it), in my case, I had forgotten to also update the SECTIONS info. Therefor it did not detect any new sections!

Share:
112,327
chandlervdw
Author by

chandlervdw

Cool guy doing cool stuff trying to be cool.

Updated on July 08, 2022

Comments

  • chandlervdw
    chandlervdw almost 2 years

    I'm attempting to learn Swift & the basics of iOS dev at the same time, so bear with me. I've got a TableViewController that is firstly parsing a local JSON file and rendering it's very simple data into TableViewCell and SectionHeaderViews. Within the same TableViewController, I'm making a call to a JSON endpoint, which is returning data, which I am then setting to variables so I can access what I actually want to get at (the API structure is less than desirable). So, I finally set the proper data to be self.tableData and then call self.tableView.reloadData() but nothing happens. What gives?

    import UIKit
    
    class BusinessTableViewController: UITableViewController {
    
        var data: NSMutableData = NSMutableData()
        var tableData: NSArray = NSArray()
    
        @lazy var Business: NSArray = {
            let pathTCT = NSBundle.mainBundle().pathForResource("TCT", ofType: "json")
            let data = NSData.dataWithContentsOfFile(pathTCT, options: nil, error: nil)
            return NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as NSArray
            }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            navigationItem.titleView = UIImageView(image: UIImage(named: "growler"))
    
            tableView.registerClass(BeerTableViewCell.self, forCellReuseIdentifier: "cell")
            tableView.separatorStyle = .None
    
            fetchKimono()
        }
    
        override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
    //        return Business.count
            return 1
        }
    
        override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
            let biz = Business[section] as NSDictionary
            let results = biz["results"] as NSDictionary
            let beers = results["collection1"] as NSArray
            return beers.count
        }
    
        override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
            let cell = tableView!.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath!) as BeerTableViewCell
            if let path = indexPath {
                let biz = Business[path.section] as NSDictionary
                let results = biz["results"] as NSDictionary
                let beers = results["collection1"] as NSArray
                let beer = beers[path.row] as NSDictionary
    
                cell.titleLabel.text = beer["BeerName"] as String
            }
    
            return cell
        }
    
        override func tableView(tableView: UITableView!, titleForHeaderInSection section: Int) -> String! {
            let biz = Business[section] as NSDictionary
            return biz["name"] as String
        }
    
        override func tableView(tableView: UITableView!, viewForHeaderInSection section: Int) -> UIView! {
            let biz = Business[section] as NSDictionary
            let view = LocationHeaderView()
            view.titleLabel.text = (biz["name"] as String).uppercaseString
            return view
        }
    
        override func tableView(tableView: UITableView!, heightForHeaderInSection section: Int) -> CGFloat {
            return 45
        }
    
        func fetchKimono() {
            var urlPath = "names have been changed to protect the innocent"
            var url: NSURL = NSURL(string: urlPath)
            var request: NSURLRequest = NSURLRequest(URL: url)
            var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
    
            connection.start()
        }
    
        func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
            // Recieved a new request, clear out the data object
            self.data = NSMutableData()
        }
    
        func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
            // Append the recieved chunk of data to our data object
            self.data.appendData(data)
        }
    
        func connectionDidFinishLoading(connection: NSURLConnection!) {
            // Request complete, self.data should now hold the resulting info
            // Convert the retrieved data in to an object through JSON deserialization
            var err: NSError
            var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options:    NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
            var results: NSDictionary = jsonResult["results"] as NSDictionary
            var collection: NSArray = results["collection1"] as NSArray
            if jsonResult.count>0 && collection.count>0 {
                var results: NSArray = collection as NSArray
                self.tableData = results
                self.tableView.reloadData()
            }
        }
    }