2013-04-04 58 views
2

後立即調用的UITableView的reloadData當我有一個文本字段,顯示的建議當用戶鍵入一個名稱的表視圖。數據源的過濾在後臺線程中進行,因爲它可能需要一些時間。崩潰對方

- (IBAction)personNameChanged:(UITextField *)sender 
{ 
    NSString *name = sender.text; 

    [backgroundThread performBlock:^{ 
      [self.personsDataSource filterDataSourceByName:name]; 
      [mainThread performBlock:^{ 
       [self.autoCompleteTableView reloadData]; 
      }]; 
    }]; 
} 

[UITableView reloadData]電話:

  • -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

...同步而所有細胞:

  • - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

...在稍後的時間點被調用。

的問題是,當用戶快速打字它可能發生的所有細胞都加載之前filterDataSourceByName被調用。然後cellForRowAtIndexPath被調用一個不存在的indexPath。

你應該如何調用reloadData時速度太快,這樣是沒有加載的所有細胞從上次重裝解決這個問題?

回答

8

新的數據源數組表視圖的分配新建分配FY也必須在主線程來完成,像這樣:

- (IBAction)personNameChanged:(UITextField *)sender 
{ 
    NSString *name = sender.text; 
    [backgroundThread performBlock:^{ 
      // Store filtered array into separate array here: 
      NSArray *filteredPersons = [self.personsDataSource filterDataSourceByName:name]; 
      [mainThread performBlock:^{ 
       // Assign to table view data source array here: 
       self.dataSourceArray = filteredPersons; 
       [self.autoCompleteTableView reloadData]; 
      }]; 
    }]; 
} 

否則有可能發生的是,數據源陣列是在後臺修改線程,同時被主線程上的表視圖訪問。

+1

似乎工作,謝謝!就一個問題;這個解決方案依賴於所有的單元格被加載,然後再次進入mainThread塊。我們確定在我們第二次輸入mainThread performBlock之前,單元的所有加載都發生了嗎? – thejaz 2013-04-04 13:50:35

+0

@thejaz:我不明白爲什麼這取決於哪些單元格被加載或沒有。 – 2013-04-04 13:55:26

+0

我的解決方案的問題是,在所有單元格被加載之前,數組已被過濾,並且當一個單元格在數組發生更改後嘗試加載時 - 那是當我得到錯誤時。在你的場景中 - 再次獲得相同錯誤的唯一可能原因是表視圖開始加載其所有單元格。但在完成所有單元之前,mainThread performBlock將再次執行。所以問題是如果mainThread performBlock可以在加載單元格之前執行。我想這取決於如何將單元格的加載放置在某種隊列中? – thejaz 2013-04-04 14:03:52