self.tableView.reloadData()在Swift中不起作用
我试图同时学习Swift和iOS开发的基础知识,所以请耐心等待。 我有一个TableViewController,它首先parsing本地的JSON文件,并将其非常简单的数据转换为TableViewCells和SectionHeaderViews。 在同一个TableViewController中,我正在调用一个JSON端点,该端点正在返回数据,然后我将其设置为variables,以便我可以访问我实际想要获取的数据(API结构不太理想)。 所以,我终于设置适当的数据是self.tableData,然后调用self.tableView.reloadData()但没有任何反应。 是什么赋予了?
(有关的代码是在这个类的底部)
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() } } }
您需要通过以下方式在UI线程上重新加载表格:
//swift 2.3 dispatch_async(dispatch_get_main_queue(), { () -> Void in self.tableView.reloadData() }) //swift 3 DispatchQueue.main.async{ self.tableView.reloadData() }
跟进:对于connection.start()方法来说,更简单的方法是使用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() }
这不允许您灵活地跟踪字节,例如,您可能想要通过bytesDownloaded / bytesNeeded计算下载的进度
你只需input:
首先是IBOutlet:
@IBOutlet var appsTableView : UITableView
然后在一个动作function:
self.appsTableView.reloadData()
在我的情况下表正确更新,但setNeedDisplay()没有被调用的图像,所以我误以为数据没有重新加载。
如果你的连接在后台线程,那么你应该像这样更新主线程中的UI
self.tblMainTable.performSelectorOnMainThread(Selector("reloadData"), withObject: nil, waitUntilDone: true)
正如我在这里提到的
所以,问题是我试图不恰当地使用@lazy,这导致我的业务variables本质上是一个常量,因此是不可修改的。 此外,而不是加载本地JSON,我现在只加载从API返回的数据。
import UIKit class BusinessTableViewController: UITableViewController { var data: NSMutableData = NSMutableData() var Business: NSMutableArray = NSMutableArray() 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 } override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int { if (Business.count > 0) { let biz = Business[section] as NSDictionary let beers = biz["results"] as NSArray return beers.count } else { return 0; } } 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 beers = biz["results"] as NSArray let beer = beers[path.row] as NSDictionary cell.titleLabel.text = beer["BeerName"] as String } else { cell.titleLabel.text = "Loading" } return cell } override func tableView(tableView: UITableView!, viewForHeaderInSection section: Int) -> UIView! { let view = LocationHeaderView() let biz = Business[section] as NSDictionary if (Business.count > 0) { let count = "\(Business.count)" 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 removed 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 { Business = jsonResult tableView.reloadData() } } }
@lazy上的Swift Docs :
您必须始终将lazy属性声明为variables(使用var关键字),因为在实例初始化完成之前,可能不会检索其初始值。 在初始化完成之前,常量属性必须始终有一个值,因此不能声明为惰性。
除了从UI /主线程(无论苹果电话它)明显的reloadData,在我的情况下,我忘了也更新SECTIONS信息。 因此,它没有发现任何新的部分!