2013-04-04 57 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