确保UITableView以原子方式重新加载的最佳方法是什么?

时间:2013-08-07 15:56:56

标签: ios uitableview atomic

我有一个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)块,但是我想尽可能避免这种情况,因为它很昂贵。

1 个答案:

答案 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中有更详细的解释。