UITableView cellForRowAtIndexPath被提前调用

时间:2014-04-25 16:14:27

标签: ios objective-c nsarray uitableview

我有一个UITableView可以在第一次调用时加载其数组项。但是,当我刷新tableview时它会崩溃,因为委托方法cellForRowAtIndexPath会被提前调用。我有一个整数,表示我的主数据数组的索引,并在我的刷新按钮中重置为0。然而它崩溃是因为它试图在重置之前重新加载数据。我通常会使用indexPath.row作为我的索引,但是数组很复杂,并且indexPath.row与我想要为每个单元格显示的内容不匹配。下面是一些代码,感谢任何帮助。

当我在viewDidLoad中下拉刷新AND以准备数据

时,会调用此方法
- (IBAction)refresh:(id)sender {
itemIndexer = 0;
[sender beginRefreshing];
[self loadData];
}

我的loadData方法的一部分

-(void) loadData {
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.Foo.myqueue", 0);
dispatch_queue_t mainQueue = dispatch_get_main_queue();

dispatch_async(backgroundQueue, ^{

   [self downloadData];

    dispatch_async(mainQueue, ^{
            [self.tableView reloadData];
            [_rcRefresh endRefreshing];
    });
});

在viewDidLoad中,我调用最初加载tableview:

[self refresh:_rcRefresh];

我得到一个超出数组错误范围的索引。我使用断点来确定原因,原因很简单,因为刷新并没有被调用,否则itemIndexer将被设置为0.而是比数组大小大1。如果它真的有必要我可以发布cellForRowAtIndexPath但是我不确定你是否需要它,如果它在第一次调用时工作。因此,总结对tableview的第一次调用是否有效并且数据加载正常但是刷新会导致索引超出数组的边界,就像从不调用refresh:一样。

2 个答案:

答案 0 :(得分:5)

对于你说的话,我只能猜测:

  • 您的numberOfSectionsInTableView / numberOfRowsInSection返回的号码错误。

  • 如果[self downloadData]是异步的(您正在发出服务器请求而不是等待响应),则应在获得数据后重新加载数据。

  • 您下载的数据未与您已有的数据正确合并。

更多代码(numberOfSectionsInTableView,numberOfRowsInSection,cellForRowAtIndexPath,downloadData)肯定会有所帮助。

答案 1 :(得分:2)

为了清晰起见,要点几点......

  • 正如@ k20所示,并不是过早调用tableView:cellForRowAtIndexPath:,而是在异步流程/方法完成后需要更好地管理下载数据。
  • tableView:cellForRowAtIndexPath:UITableView数据源方法,而不是委托方法。值得一提的是这个迂腐的细节,因为它可以帮助您或其他人更好地理解您正在编写的代码。 ;)

表视图方法调用就是它们 - 据我所知,每次UITableViewControllerinitawakeFromNib时,所有表视图方法都会按顺序调用。您必须覆盖的内容(tableView:numberOfRowsInSection:& tableView:cellForRowAtIndexPath:)以及您选择覆盖的内容仍将以相同的顺序执行。

因此,对于您的问题,更合适的标题可能是......"如何使用异步线程上的下载数据更新UITableView。"

再次@ k20指向正确的解决方案。您是否尝试过这两行代码......

        [self.tableView reloadData];
        [_rcRefresh endRefreshing];

在您的异步调用中,而不是回到主队列中?

可能是你编写的代码正在执行这样......

  1. dispatch_q_t;
  2. 准备局部变量
  3. 开始下载过程;
  4. 重新加载表格视图的数据;
  5. 结束刷新[_rcRefresh endRefreshing];
  6. 取决于所需的时间,然后完成下载过程;
  7. 你显然想要像这样执行...

    1. dispatch_q_t;
    2. 准备局部变量
    3. 开始下载过程;
    4. 取决于所需的时间,完成下载过程;
    5. 重新加载表格视图的数据;
    6. 结束刷新[_rcRefresh endRefreshing];
    7. 试试我的建议,让我知道你怎么走。希望有所帮助。