我有一个 UITableView,它的数据源在很短的时间内随机更新。随着更多对象被发现,它们被添加到 tableView 的数据源中,我插入特定的 indexPath:
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
数据源位于管理器类中,更改时发布通知。
- (void)addObjectToDataSource:(NSObject*)object {
[self.dataSource addObject:object];
[[NSNotificationCenter defaultCenter] postNotification:@"dataSourceUpdate" object:nil];
}
viewController 在收到此通知时更新 tableView。
- (void)handleDataSourceUpdate:(NSNotification*)notification {
NSObject *object = notification.userInfo[@"object"];
NSIndexPath *indexPath = [self indexPathForObject:object];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
这工作正常,但我注意到在某些情况下,第二个对象被发现就像第一个对象调用 endUpdates 一样,我得到一个异常,声称我的数据源中有两个对象,而 tableView 期望一个对象。
我想知道是否有人找到了一种更好的方法来自动将行插入到 tableView 中。我正在考虑在更新周围放置一个 @synchronized(self.tableView) block ,但我想尽可能避免这样做,因为它很昂贵。
最佳答案
我推荐的方法是创建一个私有(private)队列,用于将批量更新同步发布到主队列(其中 addRow
是一种将项目插入数据模型中给定 indexPath 的方法) :
@interface MyModelClass ()
@property (strong, nonatomic) dispatch_queue_t myDispatchQueue;
@end
@implementation MyModelClass
- (dispatch_queue_t)myDispatchQueue
{
if (_myDispatchQueue == nil) {
_myDispatchQueue = dispatch_queue_create("myDispatchQueue", NULL);
}
return _myDispatchQueue;
}
- (void)addRow:(NSString *)data atIndexPath:(NSIndexPath *)indexPath
{
dispatch_async(self.myDispatchQueue, ^{
dispatch_sync(dispatch_get_main_queue(), ^{
//update the data model here
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
});
});
}
通过这种方式,您不会阻塞任何其他线程,并且基于 block 的方法可确保 TableView 的动画 block (抛出异常的 block )以正确的顺序执行。 Rapid row insertion into UITableView causes NSInternalInconsistencyException中有更详细的解释.
关于ios - 确保 UITableView 以原子方式重新加载的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18108095/