Using KVO for Table Update
2013-08-27 18:40
323 查看
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 reloadData, insertRowsAtIndexPaths: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:
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.
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.
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 reloadData, insertRowsAtIndexPaths: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.
相关文章推荐
- 处理MySQL更新表时Error Code: 1175. You are using safe update mode and you tried to update a table……
- mysql异常:You can't specify target table 'my' for update in FROM clause
- mysql错误:1093-You can’t specify target table for update in FROM clause的解决方法
- You are using safe update mode and you tried to update a table without a WHERE that uses a KEY colum
- MYSQL之You can't specify target table for update in FROM clause解决办法
- My Asp.net Ajax Trip(一) ----Using For UpdatePanel
- mysql中You can't specify target table for update in FROM clause错误
- MySQL can’t specify target table for update in FROM clause
- mysql update完root用户密码后,再登陆报错”Access denied for user 'root'@'localhost' (using password: YES)“的解决方法
- Error Code: 1175. You are using safe update mode and you tried to update a table
- unable to update security settings Access denied for user 'root@localhost(using password:yes)'
- MySQL [Err] 1093 - You can't specify target table 'test' for update in FROM clause
- MySQL错误:You are using safe update mode and you tried to update a table without a WHERE that uses a K
- Mysql: Table name is specified twice, both as a target for UPDATE and as a separate source for data
- MySQL can’t specify target table for update in FROM clause
- mysql中You can't specify target table for update in FROM clause
- MySQL错误:You are using safe update mode and you tried to update a table without a WHERE that uses a K
- [Err] 1093 - You can't specify target table 'image' for update in FROM clause
- Mysql Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
- rror Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnec