2015-11-06 228 views
0

我有一個UITableView,這應該使條目分爲部分。 數據需要處理一定的時間,因此它的工作是這樣的:UITableViewDataSource異步加載

@interface AsyncTable() 
    NSMutableArray* _alphaKeys; 
@end 

@implementation AsyncTable   
-(void)refreshData { 
     dispatch_async(_serialQueue, ^{ 
      <load of the _alphaKeys> 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [table reloadData]; 
      }); 
     }); 
} 
... 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return [_alphaKeys count]; 
} 
... 
@end 

現在,這個完美的作品首次。

但我的數據有時會改變,我從通知調用方法refreshData。 並且它正在開始崩潰,例如在執行numberOfSectionsInTableView,並在cellForRowAtIndexPath時間的陣列可以具有不同的內容的引用。

問題是時機,讓我們假設有2級呼叫的每相繼到來短: 第一個是加載完成並在主線程調度reloadData,然後第二個請求是與數據的重載啓動主線程調用之前...

任何建議如何解決這個問題?我不想把所有東西都放在主線程中(它可以工作,我現在試圖重構應用程序以使它更具響應性)

+1

'reloadData' SUD沒有在後臺被調用,它的錯誤的方式重新加載'tableView' – Mukesh

+0

@muku'reloadData'不是從後臺調用,這是調用主線程(請參閱上面的代碼)。或者我錯過了這一點?我想在後臺處理完成後調用reload –

+1

嗨。 1)第一種方法是用'NSOperation'重構代碼。這是允許您取消以前的操作。 2)第二種方法是添加一個追加加載狀態的變量。在調用'[table reloadData]'之前,你需要檢查這個變量。 –

回答

1

您的問題是由於更新數據源(_alphaKeys)與tableView loading 。 UITableView異步加載,無法分辨何時完成。但是,如果更改數據源並立即調用reloadData,即使正在進行加載,它也會做正確的事情。訣竅是數據的改變必須在主線程上完成。

我對您的回答是更改您的代碼,以便後臺線程在一份數據上進行處理。當處理完成後,主線程新的數據複製到表視圖的數據源,然後立即打電話reloadData上運行的模塊。

見我修改您的示例代碼:

@interface AsyncTable() 
    NSArray* _alphaKeys; // <-- copy for data source is immutable 
@end 

@implementation AsyncTable   
-(void)refreshData { 
     dispatch_async(_serialQueue, ^{ 
      NSMutableArray *alphaKeysCopy = [_alphaKeys mutableCopy]; // <-- Create a new array if processing does not require current state 
      <load of the alphaKeysCopy> 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       _alphaKeys = [alphaKeysCopy copy]; // <-- Copy on the main thread so the table view can't see an intermediate state 
       [table reloadData]; 
      }); 
     }); 
} 
+0

謝謝!這是個好主意。另外一個問題是:'但是,如果更改數據源並立即調用reloadData,即使加載正在進行,它也會做正確的事情 - 您從哪裏得到它?上面的@Mozilla提示起作用,但我不是100%肯定的,就像我不知道如何實現'reloadData'一樣。如果這只是一堆異步調用來獲取行數,在不同的塊中繪製每一個raw等等,我的代碼的第二次調用會在主要隊列中的這些調用之間插入另一個_alphaKeys副本。你不這麼認爲? –

+1

表視圖(重新)加載是一個實現細節,但我的實驗顯示'reloadData'設置狀態並觸發該過程。在連續的循環中,調用數據源方法(numberOfRowsInSection,numberOfSections,cellForRowAtIndexPath等)來構建表。如果您在第一次調用之後在runloop迭代中調用'reloadData',則該表只會重置並重新開始。 – Avi