5

非常に短期間にランダムな間隔で dataSource が更新された 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 を呼び出しているときに 2 番目のオブジェクトが検出され、tableView が 1 つを予期していたときに、データ ソースに 2 つのオブジェクトがあると主張する例外が発生することに気付きました。

tableViewに行をアトミックに挿入するより良い方法を誰かが見つけたのではないかと思っていました。更新の前後に@synchronized(self.tableView)ブロックを入れようと思っていたのですが、コストがかかるのでできれば避けたいです。

4

1 に答える 1

4

私が推奨する方法は、バッチ更新をメイン キューに同期的にポストするためのプライベート キューを作成することです (ここ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];
        });
    });
}

このようにすることで、他のスレッドをブロックせず、ブロックベースのアプローチにより、テーブル ビューのアニメーション ブロック (例外をスローしているブロック) が正しい順序で実行されることが保証されます。UITableView への迅速な行挿入により NSInternalInconsistencyException が発生するに、より詳細な説明があります。

于 2013-08-07T18:28:27.397 に答える