2013-08-07 64 views
4

我有一個UITableView,它的dataSource在很短的時間內隨機更新。隨着越來越多的對象被發現,他們將被添加到的tableView的數據源和我插入特定indexPath:什麼是確保UITableView自動重新加載的最佳方式?

[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)塊,但是我想避免這種情況,因爲它很貴。

回答

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有更詳細的解釋。

+0

這個問題是我正在顯示的實際數組是在一個單獨的類中更新的,我發送一個通知到我的tableView類來重新加載行以反映這一點。所以我無法將tableView更新發送到主隊列的末尾,因爲在執行時,數據源將發生更改。 – Mark

+0

這不應該是一個問題。事實上,我所鏈接的解決方案就是這樣。我只是簡化了代碼,因爲你沒有說你這樣做:)訣竅是你更新數據模型並在同一個塊內發佈通知。 –

+0

在您鏈接的示例中,在調度同步塊中修改了陣列。我的數組將在addRow:atIndexPath:被執行之前被修改。 – Mark

相關問題