插入新 table 行后移动了 UITableView 部分页脚
UITableView section footer moved after inserting new table rows
我有一个显示项目列表的 UITableView。 table 视图控制器有一个项目数组,这些项目在响应对 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
}
}
我希望这个 table 的每个部分都有一个带按钮的页脚,所以我也包括这个:
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()
}
}
这一切都很好,但是当我知道一次只添加一个项目时,我对 table 的 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)
}
}
当我这样做时,table 继续工作,但页脚按钮有问题。我没有在每个部分的页脚中显示我创建的添加按钮,而是在 table 视图底部第 1 部分下方看到第 0 部分的添加按钮。
似乎可以通过强制刷新 table 来解决问题。这个 UITableViewController 是 UINavigationController 中的顶级控制器,如果我 select 一个 table 单元格,一个新的视图控制器将被推送到导航控制器上。导航回原来的 table 视图控制器,页脚按钮显示在正确的位置。
完成这项工作的最简单方法就是使用 reloadData
而不是 insertRowsAtIndexPaths
。但是我想知道我在这里做错了什么,这样我就可以避免重新加载所有 table 数据。
我在这里使用 insertRowsAtIndexPaths
不正确吗?
我认为发生这种情况是因为缺少 beginUpdates() 和 endUpdates() 并且这是一个非常简单的错误。但是我在测试时遇到了完全相同的问题。
我只是分享一下我的观察。
当我尝试 tableView style Grouped 时,上面的问题没有发生。但是如果我使用 Plain 样式,页脚会下降到 table 视图的底部。我想这与不同的页脚视图行为有关,这取决于它的样式和更新数据后 table 查看布局其内容的方式。
如果必须使用 tablePlain 样式的视图,则必须处理其内容的高度总和(单元格和部分页脚视图)小于 table 的情况在插入行之前查看高度。
像,
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
}
为了让一切变得干净,您应该了解 table 视图的 footer/header 部分的不同样式和框架的行为。希望您能找到更符合您要求的解决方案。
我有一个显示项目列表的 UITableView。 table 视图控制器有一个项目数组,这些项目在响应对 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
}
}
我希望这个 table 的每个部分都有一个带按钮的页脚,所以我也包括这个:
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()
}
}
这一切都很好,但是当我知道一次只添加一个项目时,我对 table 的 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)
}
}
当我这样做时,table 继续工作,但页脚按钮有问题。我没有在每个部分的页脚中显示我创建的添加按钮,而是在 table 视图底部第 1 部分下方看到第 0 部分的添加按钮。
似乎可以通过强制刷新 table 来解决问题。这个 UITableViewController 是 UINavigationController 中的顶级控制器,如果我 select 一个 table 单元格,一个新的视图控制器将被推送到导航控制器上。导航回原来的 table 视图控制器,页脚按钮显示在正确的位置。
完成这项工作的最简单方法就是使用 reloadData
而不是 insertRowsAtIndexPaths
。但是我想知道我在这里做错了什么,这样我就可以避免重新加载所有 table 数据。
我在这里使用 insertRowsAtIndexPaths
不正确吗?
我认为发生这种情况是因为缺少 beginUpdates() 和 endUpdates() 并且这是一个非常简单的错误。但是我在测试时遇到了完全相同的问题。
我只是分享一下我的观察。
当我尝试 tableView style Grouped 时,上面的问题没有发生。但是如果我使用 Plain 样式,页脚会下降到 table 视图的底部。我想这与不同的页脚视图行为有关,这取决于它的样式和更新数据后 table 查看布局其内容的方式。
如果必须使用 tablePlain 样式的视图,则必须处理其内容的高度总和(单元格和部分页脚视图)小于 table 的情况在插入行之前查看高度。 像,
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
}
为了让一切变得干净,您应该了解 table 视图的 footer/header 部分的不同样式和框架的行为。希望您能找到更符合您要求的解决方案。