简体   繁体   English

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

[英]UITableView - how do you reload with completely new data?

I've got a table view showing the output of a search. 我有一个显示搜索结果的表格视图。 When I update it to show the output of a totally different search if the old set of results was longer then old cells remain below my new ones. 当旧结果集较长时,如果对其进行更新以显示完全不同的搜索的输出,则旧单元格仍低于新单元格。

For examples, if my first results are: 例如,如果我的第一个结果是:

[Sam,
Joe,
Sally,
Betty,
Bob]

then I have five cells, one per result, as expected. 然后我有五个单元格,每个结果一个,如预期的那样。 If my second set of results is short, say just 如果我的第二组结果很短,那就说

[Smith]

then I now have five cells ( Smith , Joe, Sally, Betty and Bob), when only one (Smith) is expected. 那么我现在有五个单元格( 史密斯 ,乔,萨利,贝蒂和鲍勃),而只需要一个(史密斯)。

Here's how I'm reloading: 这是我的重新加载方式:

results = getResults()
tableView.reloadData()

And here's how I'm getting the number of cells: 这是我获取细胞数量的方法:

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
}

which is printing out "Table has 1 rows." 正在打印“表有1行”。 as expected, but the four old rows are still there. 和预期的一样,但四排旧书仍然存在。

Now, I could delete them before reloading, or delete the whole section, but is there a better way of achieving this? 现在,我可以在重新加载之前将其删除,或者删除整个部分,但是有更好的方法吗? I thought reloadData would reload everything. 我认为reloadData将重新加载所有内容。


Additional Info 附加信息

Here's cellForRowAtIndexPath as requested: 这是所请求的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
}

And just to prove we have the right number of rows I put a println in before reloadData(): 只是为了证明我们有正确的行数,我在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()

Which outputs 哪个输出

Table has 1 rows. 表有1行。
We're about to reload the table view, we have 1 sections and 1 rows in sections 0 我们将要重新加载表格视图,我们有1个部分,第1部分中有1行
Table has 1 rows. 表有1行。

as it should. 正如它应该。

Something else I've noticed, which surely has to be related - the table doesn't update at all until I try scrolling. 我注意到的其他一些东西肯定与之相关-在尝试滚动之前,表格根本不会更新。 What am I missing? 我想念什么? I know reloadData has been called as println is being called within numberOfRowsInSection. 我知道reloadData已被调用,因为在numberOfRowsInSection中正在调用println。


Update 更新

The textFieldShouldReturn method that triggers the update includes this code: 触发更新的textFieldShouldReturn方法包含以下代码:

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

which seems very likely to be the culprit. 这似乎很可能是罪魁祸首。 Is there a better way of checking for permission? 有没有更好的检查权限的方法? I included it there so that if the user ever disallowed it it would ask again next time they try to use it, rather than just failing. 我将其包含在此处,以便如果用户禁止使用它,它将在下一次尝试使用它时再次询问,而不仅仅是失败。

The problem was indeed the fact that reloadData was taking place in another thread due to the eventStore.requestAccessToEntityType call. 问题确实是由于eventStore.requestAccessToEntityType调用导致reloadData在另一个线程中发生的事实。

There are two solutions: 有两种解决方案:

1) Perform the permissions check once, when the app loads, instead of every time you access the the EventStore, as suggested by Paulw11. 1)在应用加载时执行一次权限检查,而不是像Paulw11所建议的那样每次访问EventStore都要执行一次权限检查。 This means for the majority of the application there's only one thread. 这意味着对于大多数应用程序来说,只有一个线程。

2) Use the following code to execute reloadData on the main thread: 2)使用以下代码在主线程上执行reloadData:

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

as suggested by almas. 如阿尔玛斯所建议。

Update: I've just checked and if you revoke the permission for the app to access the Calendar then it doesn't ask the user again anyway, it just denies access, so there's no reason to keep the eventStore.requestAccessToEntityType where it is. 更新:我刚刚检查了一下,如果您撤消了该应用程序访问日历的权限,那么它无论如何都不会再次询问用户,它只是拒绝访问,因此没有理由将eventStore.requestAccessToEntityType保留在原处。

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

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