简体   繁体   English

UITableView cellForRowAtIndexPath被提前调用

[英]UITableView cellForRowAtIndexPath gets called to early

I have a UITableView that loads its array items fine on the first call. 我有一个UITableView可以在第一次调用时很好地加载其数组项。 However when i refresh the tableview it crashes because the delegate method cellForRowAtIndexPath gets called to early. 但是,当我刷新tableview时,它会崩溃,因为委托方法cellForRowAtIndexPath被提早调用。 I have an integer which represents the index of my main data array and this gets reset to 0 in my refresh button. 我有一个整数,代表我的主数据数组的索引,并且在刷新按钮中将其重置为0。 However its crashing because its trying to reload the data before its been reset. 但是它崩溃是因为它试图在重置之前重新加载数据。 I would normally use indexPath.row as my index however the array is complicated and the indexPath.row will not match up to what i want to show for each cell. 我通常将indexPath.row用作索引,但是该数组很复杂,并且indexPath.row不会与我要显示的每个单元格匹配。 Heres some code, any help is appreciated. 继承人一些代码,任何帮助表示赞赏。

This gets called when i pull down to refresh AND in viewDidLoad to prepare the data 当我下拉刷新并在viewDidLoad中准备数据时调用此方法

- (IBAction)refresh:(id)sender {
itemIndexer = 0;
[sender beginRefreshing];
[self loadData];
}

Part of my loadData method 我的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];
    });
});

In viewDidLoad i call to initially load the tableview: 我在viewDidLoad中调用以初始加载tableview:

[self refresh:_rcRefresh];

I am getting a index outside bounds of array error. 我正在索引超出数组错误的范围。 Which i have used breakpoints to determine why, the reason is simply because the refresh isn't getting called at all otherwise itemIndexer would be set to 0. Instead its a number 1 greater than the array size. 我使用断点来确定原因的原因仅仅是因为根本不调用刷新,否则itemIndexer将被设置为0。相反,它比数组大小大1。 If its really necessary i can post cellForRowAtIndexPath however I'm unsure if you need it if it works on the first call. 如果确实有必要,我可以发布cellForRowAtIndexPath,但是我不确定是否可以在第一次调用时使用它。 So to summarise the first call to the tableview works and the data is loaded fine however the refresh causes the index to be outside the bounds of the array as if refresh: is never called. 因此,总结一下对tableview的第一次调用是可行的,并且数据加载良好,但是刷新使索引超出了数组的范围,就好像从未调用过refresh:一样。

For what you say, I can only try guessing: 对于您所说的,我只能尝试猜测:

  • Your numberOfSectionsInTableView/numberOfRowsInSection is returning a wrong number. 您的numberOfSectionsInTableView / numberOfRowsInSection返回错误的数字。

  • If [self downloadData] is asynchronous (you are making a server request and not waiting for the response), you should reloadData once you have the data. 如果[self downloadData]是异步的(正在发出服务器请求,而不是在等待响应),则在拥有数据后应重新加载Data。

  • The data you download is not merged properly with the data you already have. 您下载的数据未与您已有的数据正确合并。

Some more code (numberOfSectionsInTableView, numberOfRowsInSection, cellForRowAtIndexPath, downloadData) would definitely help. 当然,更多的代码(numberOfSectionsInTableView,numberOfRowsInSection,cellForRowAtIndexPath,downloadData)肯定会有所帮助。

Couple of points for clarity... 为了清楚起见,有几点...

  • As indicated by @k20, it is not that tableView:cellForRowAtIndexPath: is called too early, but that you need to better manage your download data once your asynchronous process / method has completed. 如@ k20所示,并不是太早调用tableView:cellForRowAtIndexPath:但是一旦异步过程/方法完成,您就需要更好地管理下载数据。
  • tableView:cellForRowAtIndexPath: is a UITableView data source method, not a delegate method. tableView:cellForRowAtIndexPath:UITableView数据源方法,而不是委托方法。 It is worth mentioning this pedantic detail because it may help you or others better understand the code you are writing. 值得一提的是这个脚的细节,因为它可以帮助您或其他人更好地理解您正在编写的代码。 ;) ;)

The table view method calls are what they are - as I understand it, all table view methods are called in order, each time a UITableViewController is init or awakeFromNib . 表视图方法调用就是它们的含义-据我了解,每次UITableViewController initawakeFromNib时,所有表视图方法都按顺序调用。 Those that you must override ( tableView:numberOfRowsInSection: & tableView:cellForRowAtIndexPath: ), and those that you choose to override will still execute in that same order. 您必须覆盖的表( tableView:numberOfRowsInSection:tableView:cellForRowAtIndexPath: ,以及您选择覆盖的表仍将以相同的顺序执行。

Therefore a more appropriate title for your question might be... "How to update a UITableView with data from a download on an asynchronous thread." 因此,可能更适合您的问题的标题是:“如何使用异步线程上的下载数据更新UITableView。”

Again @k20 is pointing you to the correct solution. @ k20再次指出正确的解决方案。 Have you attempting placing these two lines of code... 您是否尝试放置这两行代码...

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

within your async call, instead of back in the main queue? 在您的异步调用中,而不是返回主队列中?

It may be that your code as written is executing like this... 可能是您编写的代码正在像这样执行...

  1. Prepare local variables for dispatch_q_t ; dispatch_q_t准备局部变量;
  2. Commence download process; 开始下载过程;
  3. reload data for table view; 重新加载数据以用于表视图;
  4. end the refresh [_rcRefresh endRefreshing] ; 结束刷新[_rcRefresh endRefreshing] ;
  5. depending on time it takes, then finish download process; 根据所需的时间,然后完成下载过程;

Where you obviously would like to execute like this... 您显然想执行的地方...

  1. Prepare local variables for dispatch_q_t ; dispatch_q_t准备局部变量;
  2. Commence download process; 开始下载过程;
  3. depending on time it takes, finish download process; 根据所需的时间,完成下载过程;
  4. reload data for table view; 重新加载数据以用于表视图;
  5. end the refresh [_rcRefresh endRefreshing] ; 结束刷新[_rcRefresh endRefreshing] ;

Try my suggestion and let me know how you go. 尝试我的建议,让我知道你的情况。 Hope that helps. 希望能有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM