我有一个UITableView,其dataSource在很短的时间内以随机的间隔更新。随着更多对象的发现,它们被添加到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)块,但是我想尽可能避免这种情况,因为它很昂贵。
答案 0 :(得分:3)
我建议的方法是创建一个私有队列,用于将批量更新同步发布到主队列上(其中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];
});
});
}
通过这种方式,您不会阻止任何其他线程,并且基于块的方法可确保表视图的动画块(抛出异常的那些)以正确的顺序执行。 Rapid row insertion into UITableView causes NSInternalInconsistencyException中有更详细的解释。