I have a UITableView that displays a list of items. The table view controller has an array of items that gets updated asynchronously upon response from a call to a web service. Here is an example of what I have (in 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
}
}
I want each section of this table to have a footer with a button in it, so I also include this:
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
}
Items are added to the items
array via an callback that gets invoked outside of the main UI thread. It looks something like this:
private func itemWasAdded(item: ItemClass) {
dispatch_async(dispatch_get_main_queue()) {
self.items += [item]
self.tableView!.reloadData()
}
}
This all works fine, but my use of the table's reloadData
seems like overkill to me when I know that only one item is being added at a time. So, I tried to update it to do the following:
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)
}
}
When I do it this way, the table continues to work but there's a problem with the footer buttons. Instead of showing the Add button I've created in each section's footer, I see the add button for section 0 showing at the bottom of the table view, underneath section 1.
It seems like doing something to force a refresh of the table seems to fix the problem. This UITableViewController is the top controller in a UINavigationController, and if I select a table cell a new view controller is pushed onto the navigation controller. Navigating back to the original table view controller, the footer buttons are displayed in the correct place.
The easiest way to make this work is just to use reloadData
instead of insertRowsAtIndexPaths
. But I'd like to know what I'm doing wrong here so that I can avoid reloading all table data if possible.
Am I using the insertRowsAtIndexPaths
incorrectly here?