iOS:tableView.reloadData() 不能快速工作

Posted

技术标签:

【中文标题】iOS:tableView.reloadData() 不能快速工作【英文标题】:iOS: tableView.reloadData() doesn't work in swift 【发布时间】:2014-11-26 20:27:30 【问题描述】:

我试图在 Swift 中更新数据后重新加载我的表格视图,但它似乎不起作用。当我更改选项卡并返回时,表格视图会重新加载,但不会自动加载。 这是我的代码:

override func viewDidLoad() 
    super.viewDidLoad()

    // some code

    refresh(self)


func refresh(sender: AnyObject) 
    // Reload the data

    self.tableView.reloadData()

我不明白为什么它在 Objective-C 中有效,但在 Swift 中无效... 我也试着说:

dispatch_async(dispatch_get_main_queue(),  () -> Void in
    self.tableView.reloadData()
)

因为我在其他帖子中看到了这个,但它也不起作用。

感谢您的帮助

编辑:我的整个视图控制器

class HighwaysViewController: UITableViewController 

    var highways: [Highway]!

    override func viewDidLoad() 
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem()

        highways = [Highway]()

        // On ajoute le "Pull to refresh"
        refreshControl = UIRefreshControl()
        refreshControl!.addTarget(self, action: Selector("refresh:"), forControlEvents: UIControlEvents.ValueChanged)
        tableView.addSubview(refreshControl!)

        refresh(self)
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    

    func refresh(sender: AnyObject) 
        // Afficher l'icône de chargement dans la barre de status
        UIApplication.sharedApplication().networkActivityIndicatorVisible = true

        // On télécharge les autoroutes
        var url = NSURL(string: "http://theurl.com")! // URL du JSON
        var request = NSURLRequest(URL: url) // Création de la requête HTTP
        var queue = NSOperationQueue()  // Création de NSOperationQueue à laquelle le bloc du gestionnaire est distribué lorsque la demande complète ou échoué

        // Envoi de la requête asynchrone en utilisant NSURLConnection
        NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:(response: NSURLResponse!, data: NSData!, error: NSError!) ->Void in
            // Gestion des erreurs de connexion
            if error != nil 
                // Masquer l'icône de chargement dans la barre de status
                UIApplication.sharedApplication().networkActivityIndicatorVisible = false

                println(error.localizedDescription)
                let errorAlert = UIAlertView(title: "Erreur", message: error.localizedDescription, delegate: self, cancelButtonTitle: "OK")
                errorAlert.show()
            
            else 
                // Récupération du JSON et gestion des erreurs
                let json = JSON(data: data)

                if let highwaysData = json.arrayValue 
                    for highway in highwaysData 
                        var newHighway = Highway(ids: highway["Ids"].stringValue, name: highway["Name"].stringValue, label: highway["Direction"].stringValue, length: highway["Length"].stringValue, directions: highway["Direction"].stringValue, operateur: highway["Operator"].stringValue)
                        self.highways.append(newHighway)
                    
                
            
        )

        if (self.refreshControl!.refreshing) 
            self.refreshControl!.endRefreshing()
        

        tableView.reloadData() // Here is the problem

        // Masquer l'icône de chargement dans la barre de status
        UIApplication.sharedApplication().networkActivityIndicatorVisible = false
    

    // MARK: - Table view data source

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        // Return the number of rows in the section.
        return highways.count
    

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCellWithIdentifier("highwayCell", forIndexPath: indexPath) as UITableViewCell

        // Configure the cell...
        let tableCell = highways[indexPath.row]

        let nameLabel = cell.viewWithTag(1) as UILabel
        let directionLabel = cell.viewWithTag(2) as UILabel

        nameLabel.text = tableCell.name!
        directionLabel.text = tableCell.getDirections()

        return cell
    

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    
    */


【问题讨论】:

您是否只从viewDidLoad 拨打refresh()?请注意,它在每个视图控制器生命周期中只执行一次。 除了 viewDidLoad,你在哪里调用 reloadData? 另外,在 refresh 方法中不需要传递对 self 的引用 @Kirsteins 不,当用户“拉动刷新”时,我也会调用refresh() 那个分配了一个刷新控件,怎么放到tableView里面呢?请在您的问题中显示所有相关代码,而不必让我们在 cmets 中一次梳理一行 【参考方案1】:

在您的refresh 函数中,您的加载使用闭包异步完成,但是您正在更新活动指示器并在闭包之外重新加载表,因此它将在加载完成之前执行。您需要将此代码移动到闭包内并确保它在主队列上执行(因为它会更新 UI)

func refresh(sender: AnyObject) 
        // Afficher l'icône de chargement dans la barre de status
        UIApplication.sharedApplication().networkActivityIndicatorVisible = true

        // On télécharge les autoroutes
        var url = NSURL(string: "http://theurl.com")! // URL du JSON
        var request = NSURLRequest(URL: url) // Création de la requête HTTP
        var queue = NSOperationQueue()  // Création de NSOperationQueue à laquelle le bloc du gestionnaire est distribué lorsque la demande complète ou échoué

        // Envoi de la requête asynchrone en utilisant NSURLConnection
        NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:(response: NSURLResponse!, data: NSData!, error: NSError!) ->Void in
            // Gestion des erreurs de connexion
            if error != nil 
                // Masquer l'icône de chargement dans la barre de status
                UIApplication.sharedApplication().networkActivityIndicatorVisible = false

                println(error.localizedDescription)
                let errorAlert = UIAlertView(title: "Erreur", message: error.localizedDescription, delegate: self, cancelButtonTitle: "OK")
                errorAlert.show()
            
            else 
                // Récupération du JSON et gestion des erreurs
                let json = JSON(data: data)

                if let highwaysData = json.arrayValue 
                    for highway in highwaysData 
                        var newHighway = Highway(ids: highway["Ids"].stringValue, name: highway["Name"].stringValue, label: highway["Direction"].stringValue, length: highway["Length"].stringValue, directions: highway["Direction"].stringValue, operateur: highway["Operator"].stringValue)
                        self.highways.append(newHighway)
                    
                
            

            dispatch_async(dispatch_get_main_queue(), 

                if (self.refreshControl!.refreshing) 
                    self.refreshControl!.endRefreshing()
                

                self.tableView.reloadData() 

                // Masquer l'icône de chargement dans la barre de status
                UIApplication.sharedApplication().networkActivityIndicatorVisible = false
            )

        )

    

【讨论】:

非常感谢,它运行良好,现在我更好地理解了我的错误! :) PS:在闭包中我们必须用self调用变量:self.tableView.reloadData() 我已经更新了我的答案。我刚刚复制了你的代码,所以我错过了。就我个人而言,我总是使用self 来避免混淆,这也是 Obj C 的一个习惯,它总是需要的。【参考方案2】:

如果您正在使用选项卡栏控制器(听起来像您),并且在修改另一个选项卡中的某些内容后期望刷新表格,则需要从目标内部调用 tableView.reloadData()视图控制器的 viewWillAppear() 或 viewDidAppear() 方法。 viewDidLoad() 在视图控制器的生命周期内只调用一次。

【讨论】:

不,我希望在同一个选项卡中进行刷新。我只是希望我的表格视图在加载数据后刷新,但它不起作用 需要查看更多的视图控制器代码。 “加载数据”可以通过多种不同的方式完成。

以上是关于iOS:tableView.reloadData() 不能快速工作的主要内容,如果未能解决你的问题,请参考以下文章

iOS:tableView.reloadData() 在 swift3 中不起作用

tableView reloadData页面跳动问题

使用 tableView.reloadData() 重新加载 TableView 的问题

Swift:tableView.reloadData() 太慢了

使用通知中心和 tableview.reloaddata() 不刷新表视图

tableView.reloadData() 如何正确重新加载数据?