我有一个显示项目列表的UITableView。表视图控制器具有一组项,这些项在响应来自Web服务的响应时异步更新。这是我的一个例子(在Swift中):
class MyTableViewController : UITableViewController {
var items: [ItemClass] = []
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("RootCell", forIndexPath: indexPath) as UITableViewCell
if indexPath.section == 0 {
let item = items[indexPath.row]
cell.textLabel!.text = item.name
}
else if indexPath.section == 1 {
// Another section not shown here
}
return cell
}
}
我希望这个表的每个部分都有一个带有按钮的页脚,所以我也包括这个:
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let button = UIButton.buttonWithType(.System) as UIButton
button.setTitle("Add", forState:UIControlState.Normal)
if section == 0 {
button.addTarget(self, action:Selector("itemAddPressed:"), forControlEvents:UIControlEvents.TouchUpInside)
}
else if section == 1 {
// other section not shown here
}
return button
}
通过在主UI线程之外调用的回调将项添加到items
数组中。它看起来像这样:
private func itemWasAdded(item: ItemClass) {
dispatch_async(dispatch_get_main_queue()) {
self.items += [item]
self.tableView!.reloadData()
}
}
这一切都很好,但是当我知道一次只添加一个项目时,我对表reloadData
的使用似乎有些过分。所以,我尝试更新它以执行以下操作:
private func itemWasAdded(item: ItemClass) {
dispatch_async(dispatch_get_main_queue()) {
self.items += [item]
let indexPath = NSIndexPath(forRow:self.item.count - 1, inSection:0)
self.tableView!.insertRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
}
当我这样做时,表继续工作,但页脚按钮出现问题。我没有在每个部分的页脚中显示我创建的“添加”按钮,而是在第1部分下方的表格视图底部看到第0部分的添加按钮。
似乎做某事来强制刷新表似乎可以解决问题。这个UITableViewController是UINavigationController中的顶级控制器,如果我选择一个表格单元格,新的视图控制器将被推送到导航控制器上。导航回原始表格视图控制器,页脚按钮显示在正确的位置。
使这项工作最简单的方法就是使用reloadData
代替insertRowsAtIndexPaths
。但是我想知道我在这里做错了什么,这样我就可以避免重新加载所有表数据。
我在这里错误地使用了insertRowsAtIndexPaths
吗?
答案 0 :(得分:6)
我认为这种情况正在发生,因为缺少了beginUpdates()和endUpdates(),这将是一个非常简单的错误。但是当我测试它时,我遇到了完全相同的问题。
我将分享我的观察结果。
当我尝试使用tableview样式分组时,上面的问题没有发生。但是,如果我使用普通样式,页脚将下降到tableview的底部。我想这与不同的页脚视图行为有关,具体取决于它的样式以及更新数据后表格视图布局其内容的方式。
如果必须使用带有Plain样式的tableview,则必须处理在插入行之前其内容高度(单元格和截面页脚视图)的总和小于tableview高度的情况。 像,
let contentHeight = CGFloat(items.count * cellHeight + numberOfSection*footerHeight)
if contentHeight < tableViewHeight {
tableView.frame = CGRectMake(0, 0, view.frame.size.width, numberOfSection*CGFloat(items.count * cellHeight + footerHeight))
} else {
tableView.frame = viewHeight
}
为了让一切都干净,你应该了解tableview的section footer / header的行为及其不同的样式和框架。希望您能找到符合您要求的更好的解决方案。