插入新表行后,UITableView节页脚移动

时间:2015-01-06 02:10:48

标签: ios uitableview uikit

我有一个显示项目列表的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吗?

1 个答案:

答案 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的行为及其不同的样式和框架。希望您能找到符合您要求的更好的解决方案。