UITableView - 你如何重新加载全新的数据?

Posted

技术标签:

【中文标题】UITableView - 你如何重新加载全新的数据?【英文标题】:UITableView - how do you reload with completely new data? 【发布时间】:2014-11-12 21:27:02 【问题描述】:

我有一个显示搜索输出的表格视图。当我更新它以显示完全不同的搜索的输出时,如果旧的结果集更长,那么旧的单元格仍然低于我的新单元格。

例如,如果我的第一个结果是:

[Sam,
Joe,
Sally,
Betty,
Bob]

然后我有五个单元格,每个结果一个,正如预期的那样。如果我的第二组结果很短,就说吧

[Smith]

然后我现在有五个单元格(Smith、Joe、Sally、Betty 和 Bob),而预期只有一个(Smith)。

这是我重新加载的方式:

results = getResults()
tableView.reloadData()

这是我获取单元格数量的方法:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    if results != nil 
        println("Table has \(results!.count) rows.")
        return results!.count
    
    println("Table is empty.")
    return 0

正在打印“表格有 1 行”。正如预期的那样,但四个旧行仍然存在。

现在,我可以在重新加载之前删除它们,或者删除整个部分,但有没有更好的方法来实现这一点?我以为 reloadData 会重新加载所有内容。


附加信息

这里是按要求提供的 cellForRowAtIndexPath:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCellWithIdentifier("SearchEventsCell", forIndexPath: indexPath) as SearchEventsCell
    if results != nil && eventStore != nil && results!.count >= indexPath.row 
        let event = results![indexPath.row] as EKEvent
        cell.configureCellWithEvent(event)
    
    else 
        println("Couldn't dequeue the cell")
    
    return cell

为了证明我们有正确的行数,我在 reloadData() 之前放入了一个 println:

println("We're about to reload the table view, we have \(numberOfSectionsInTableView(tableView)) sections and \(tableView(tableView, numberOfRowsInSection:0)) rows in section 0")
tableView.reloadData()

哪些输出

表格有 1 行。 我们即将重新加载表格视图,我们在第 0 部分中有 1 个部分和 1 行 表有 1 行。

应该如此。

我注意到的其他一些东西肯定是相关的——在我尝试滚动之前,表格根本不会更新。我错过了什么?我知道 reloadData 已被调用,因为 println 在 numberOfRowsInSection 中被调用。


更新

触发更新的textFieldShouldReturn方法包括这段代码:

eventStore.requestAccessToEntityType(EKEntityTypeEvent,
     accessGranted, error in
        if accessGranted 
            if let searchEventsController = self.searchEventsController 
                searchEventsController.search(self.searchTextField.text)
            
        
        else 
            self.accessDenied()
        
    
)

这似乎很可能是罪魁祸首。有没有更好的方法来检查权限?我将它包含在其中,这样如果用户曾经拒绝它,它会在下次尝试使用它时再次询问,而不仅仅是失败。

【问题讨论】:

您是否在 cellForRowAtIndexPath 方法中使用了正确的结果数组?你能告诉我们这个方法的实现吗? 好的,我马上把它复制到这里。但是如果 numberOfRowsInSection 返回 1,为什么它甚至会要求行值大于 0 的行? 听起来您正在从后台队列调用reloadData - 您的数据是由异步网络请求加载的吗?尝试在主队列上调度重新加载 Longshot,但你是在主线程外调用reloadData 吗?关于它在滚动之前不会更新的注释听起来像是你这样做时可以看到的那种错误。 ...迟到 7 秒 啊,现在我认为你们俩都在做某事。当用户提交一个 textField 时调用 reload 方法,其中包括调用他们的日历,使用此代码 [将粘贴在上面]。那一定是问题不是吗?呃,这可能是一个愚蠢的问题,但我该如何解决呢?我可以只进行一次访问检查并在应用程序的剩余生命周期内假设它吗? 【参考方案1】:

问题确实是由于 eventStore.requestAccessToEntityType 调用,reloadData 发生在另一个线程中。

有两种解决方案:

1) 在应用加载时执行一次权限检查,而不是像 Paulw11 建议的那样每次访问 EventStore 时执行。这意味着大多数应用程序只有一个线程。

2) 使用如下代码在主线程上执行reloadData:

dispatch_async(dispatch_get_main_queue()) 
    self.tableView.reloadData()

按照 almas 的建议。

更新:我刚刚检查过,如果您撤销应用程序访问日历的权限,那么它不会再次询问用户,它只是拒绝访问,因此没有理由将 eventStore.requestAccessToEntityType 保留在哪里是的。

【讨论】:

以上是关于UITableView - 你如何重新加载全新的数据?的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 的 reloadRowsAtIndexPaths: (NSArray *) indexPaths 无法导致重新加载,除非你调用它两次?

Swift - 重新加载 UITableView 标题

如何在 UITableView 重新加载期间控制过渡动画? [复制]

UITableView如何在重新加载后继续滚动

如何在我查看 UITableView 时重新加载它

等到 UITableview 完成重新加载