self.tableView.reloadData() not working in Swift
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)
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!
Comments
-
chandlervdw almost 2 years
I'm attempting to learn
Swift
& the basics ofiOS
dev at the same time, so bear with me. I've got aTableViewController
that is firstly parsing a localJSON
file and rendering it's very simple data intoTableViewCell
and SectionHeaderViews. Within the sameTableViewController
, I'm making a call to aJSON
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 beself.tableData
and then callself.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() } } }