Using KVO for Table Update

http://blog.sina.com.cn/s/blog_61235faa01011y66.html

If you've followed the guidelines in Apple's Model Object Implementation Guide when creating your data model objects, you can handle your UITableView updates using KVO. This frees you from having to spread calls to reloadDatainsertRowsAtIndexPaths:withRowAnimation:, ordeleteRowsAtIndexPaths:withRowAnimation: throughout your controller class wherever the data in your table might get changed.


Instead, all you have to do is observe the keypath on your data model object that holds the collection of items being displayed in the table. The easiest way to do that is in your table view controller's viewDidLoad method, like so:

[self.data addObserver:self
forKeyPath:@"items"
options:0
context:NULL];

Then, you just implement observeValueForKeyPath:ofObject:change:context to insert or remove rows based on changes to the observed collection. The information about which rows were inserted or deleted comes in the changes dictionary stored under the key NSKeyValueChangeIndexesKey. The information comes in the form of index sets, and those have to be converted to index paths in order to update the table. But that's the only thing about this code that isn't fairly straightforward, and this implementation is fairly generic, so you should be able to pretty much copy and paste it into your controller if you want to use it.

If you do do this, make sure you remove all the other remove and insert calls, otherwise you will double-delete and double-insert, which will cause errors at runtime.

- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
NSIndexSet *indices = [change objectForKey:NSKeyValueChangeIndexesKey];
if (indices == nil)
return// Nothing to do


// Build index paths from index sets
NSUInteger indexCount = [indices count];
NSUInteger buffer[indexCount];
[indices getIndexes:buffer maxCount:indexCount inIndexRange:nil];

NSMutableArray *indexPathArray = [NSMutableArray array];
for (int i = 0; i < indexCount; i++) {
NSUInteger indexPathIndices[2];
indexPathIndices[0] = 0;
indexPathIndices[1] = buffer[i];
NSIndexPath *newPath = [NSIndexPath indexPathWithIndexes:indexPathIndices length:2];
[indexPathArray addObject:newPath];
}

NSNumber *kind = [change objectForKey:NSKeyValueChangeKindKey];
if ([kind integerValue] == NSKeyValueChangeInsertion// Rows were added
[self.tableView insertRowsAtIndexPaths:indexPathArraywithRowAnimation:UITableViewRowAnimationFade];
else if ([kind integerValue] == NSKeyValueChangeRemoval// Rows were removed
[self.tableView deleteRowsAtIndexPaths:indexPathArraywithRowAnimation:UITableViewRowAnimationFade];

}

Once you've done this, you can forget about reloading your table. Any changes made to the underlying data - even changes made on other threads (assuming your data model class is thread-safe) will automatically trigger an animated deletion or insertion. Although the code above may look a little intimidating, this actually allows a much cleaner overall design.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值