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() } } }
reloadData() :Reloads the rows and sections of the table view. Description : Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible.
A table view displays a single column of vertically scrolling content, divided into rows and sections. Each row of a table displays a single piece of information related to your app.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With