couchbaselabs/CouchCocoa — pull request #16 by sas71 (2012-02-23 11:42:26+00:00)
Title: Alternative table view update delegate: couchTableSource:updateFromQuery:previousRows:

Hi Jens,

I'd like to propose a change to the delegate handling in CouchUITableSource. The background is that I'd like to have the table view update with animations when the underlying query changes, based on which rows were added, which deleted, and which modified. (What that means is up to the delegate to determine, see my example below.)

In order to get a shot at handling the table view updates yourself, I've added the delegate

- (void)couchTableSource:(CouchUITableSource*)source updateFromQuery:(CouchLiveQuery*)query previousRows:(NSArray *)previousRows;

which, when implemented, handles the updates and prevents reloadData from being called in CouchUITableSource.

As an example, the way I use this in my app is the following:

- (void)couchTableSource:(CouchUITableSource*)source updateFromQuery:(CouchLiveQuery*)query previousRows:(NSArray *)oldRows
{
NSArray *newRows = query.rows.allObjects;
NSArray *addedIndexPaths = [self addedIndexPathsOldRows:oldRows newRows:newRows];
NSArray *deletedIndexPaths = [self deletedIndexPathsOldRows:oldRows newRows:newRows];
NSArray *modifiedIndexPaths = [self modifiedIndexPathsOldRows:oldRows newRows:newRows];

[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:addedIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView deleteRowsAtIndexPaths:deletedIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView reloadRowsAtIndexPaths:modifiedIndexPaths withRowAnimation:UITableViewRowAnimationRight];
[self.tableView endUpdates];
}

I looked into making the logic to find added/changed/deleted rows generic and add it to CouchUITableSource itself but found there are edge cases where it has issues (that's what all the "commit noise" is about). I don't know enough about the view machinery to make that work as a general case. Sort order for docs with identical keys was one of the problems I noticed, which tripped the reloading of updated rows, for example. The order could be different on subsequent calls, leading to the wrong row being reloaded.

So in order for this table view update to work you need to have a query that returns unique keys. But if you do, you can now have a nicely animated table view, which is a great plus when changes can be triggered externally and are otherwise hard to notice.

If I find time and if there's interest, I can try to look into making the sample app use this.