简体   繁体   English

UITableView重新加载数据不起作用

[英]UITableView reload data doesn't work

I have a simple iOS application written in Swift that loads JSON data downloaded over the Internet and displays it into a UITableView. 我有一个用Swift编写的简单iOS应用程序,该应用程序加载通过互联网下载的JSON数据,并将其显示在UITableView中。 When I launch the application for the first time, everything works correctly and the table displays the correct information. 当我第一次启动该应用程序时,一切正常,表显示正确的信息。

In my app, I have a button that triggers a refresh when I would like to reload the data. 在我的应用程序中,我有一个按钮,当我想重新加载数据时会触发刷新。 So I call the displayTable() method when the refresh button is tapped which downloads the data again and then calls the tableView.reloadData() method on the main thread to refresh the data but the reload does not appear to work. 因此,当点击刷新按钮时,我将调用displayTable()方法,这将再次下载数据,然后在主线程上调用tableView.reloadData()方法以刷新数据,但重新加载似乎无法正常进行。 I manually change the data on the server and hit refresh but I still have the old data cached in my application. 我手动更改了服务器上的数据,然后单击刷新,但是我的应用程序中仍然缓存了旧数据。 I can exit/kill the application and the old data stays 'stuck' forever unless I delete the app and reinstall. 我可以退出/杀死该应用程序,并且除非删除该应用程序并重新安装,否则旧数据将永远“卡住”。

I've attached the code for my ViewController below. 我在下面附加了ViewController的代码。 I've spent way too many hours looking at this and I cannot seem to find why the reloadData doesn't work. 我花了太多时间研究此问题,但似乎无法找到为什么reloadData无法正常工作的原因。 Any ideas, hints would be greatly appreciated. 任何想法,提示将不胜感激。

thanks 谢谢

--Vinny --Vinny

class ViewController: UITableViewController {

    var tableData = []

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(animated: Bool) {
        println("viewWillAppear was just called")
        super.viewWillAppear(true)

        self.displayTable()
    }

    func displayTable() {
        getJSONData("http://www.example.com/data.json") { (results, resultError) in

            if (resultError == nil) {
                if var results = results {
                    dispatch_async(dispatch_get_main_queue(), {
                        self.tableData = [] //create out data on subsequent refreshes
                        self.tableData = results
                        self.tableView.reloadData() //This doesn't appear to be working!
                    })
                } else {
                    self.displayErrorPopup()
                }
            } else {
                self.displayErrorPopup()
            }
        }
    }

    func displayErrorPopup() {
        let alertViewController = UIAlertController(title: "Error", message: "Couldn't connect to API", preferredStyle: .Alert)
        let okButton = UIAlertAction(title: "OK", style: .Default, handler: nil)
        let cancelButton = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
        alertViewController.addAction(okButton)
        alertViewController.addAction(cancelButton)
        self.presentViewController(alertViewController, animated: true, completion: nil)
    }

    //todo - extract this method into it's own class
    func getJSONData(ttAPIURL : String, completion: (resultsArray: NSArray?, resultError: NSError?) -> ()){
        let mySession = NSURLSession.sharedSession()
        let url: NSURL = NSURL(string: ttAPIURL)!

        let networkTask = mySession.dataTaskWithURL(url, completionHandler : {data, response, error -> Void in
            var err: NSError?
            if (error == nil) {
                var theJSON = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSMutableDictionary
                let results : NSArray = theJSON["list"]!["times"] as NSArray
                completion(resultsArray: results, resultError: error)
            } else {
                completion(resultsArray: nil, resultError: error)
            }
        })
        networkTask.resume()
    }

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

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("ttCell", forIndexPath: indexPath) as UITableViewCell
        let timesEntry = self.tableData[indexPath.row] as NSMutableDictionary
        cell.textLabel.text = (timesEntry["routeName"] as String)
        return cell
    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    @IBAction func refreshButtonTap(sender: AnyObject) {
        self.displayTable()
    }    
}

Ok, so you say that reloadData is not working but that is almost certainly not your problem. 好的,所以您说reloadData不起作用,但这几乎可以肯定不是您的问题。 To debug this you should: 要调试它,您应该:

  1. Make sure reloadData is actually being called (breakpoint or println ) 确保reloadData实际上被调用(断点或println
  2. Check if the UITableViewDataSource methods are being called after you call reloadData (breakpoint or println) 调用reloadData (断点或println)后,检查是否正在调用UITableViewDataSource方法
  3. Check the results array that you are getting back from the network request (probably println(results) ) 检查您从网络请求中返回的results数组(可能是println(results)

My guess is that it is failing at number 3 which means it has nothing to do with reloadData. 我的猜测是它在第3位失败,这意味着它与reloadData没有关系。 Perhaps the shared NSURLSession has caching enabled? 也许共享的NSURLSession启用了缓存? Try setting mySession.URLCache to nil . 尝试将mySession.URLCache设置为nil

Try to replace it 尝试更换它

override func viewWillAppear(animated: Bool) {
    println("viewWillAppear was just called")
    super.viewWillAppear(true)
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), { () -> Void in
        self.displayTable()
    })
}

Thanks drewag and Jirom for your answers. 感谢drewag和Jirom的回答。 Great comments that were very helpful. 很棒的评论很有帮助。 I just found my problem and its something I should have thought about earlier. 我刚刚发现了我的问题,这是我早先应该考虑的问题。 The domain which is hosting my dynamic JSON data is being protected by CloudFlare and it appears that my pages rules to disable caching for a certain directory aren't working. 托管我的动态JSON数据的域受到CloudFlare的保护,并且看来我的针对特定目录禁用缓存的页面规则无效。 So all of the JSON content was being cached and that was the reason my application wouldn't show the new data. 因此,所有JSON内容都已缓存,这就是我的应用程序不显示新数据的原因。

Thanks again guys for your responses. 再次感谢你们的答复。

--Vinny --Vinny

PS: Per Drewag's suggestion, I added an instance of NSURLSessionConfiguration which defines the behavior and policies to use when downloading data using an NSURLSession object, and set the URLCache property to nil to disable caching. PS:根据Drewag的建议,我添加了一个NSURLSessionConfiguration实例,该实例定义了使用NSURLSession对象下载数据时要使用的行为和策略,并将URLCache属性设置为nil以禁用缓存。

let config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.URLCache = nil
let mySession = NSURLSession(configuration: config)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM