当异步调用存在时,从cellForRowAtIndexPath返回单元格

Ant*_*ony 0 objective-c uitableview ios

在为tableview返回单元格时,我在视图控制器中遇到问题.我正在使用Parse后端来获取文件.那里有2个异步调用.据我所知,此外的代码将首先执行,依赖于结果的代码应该在块中.

简而言之,我的代码如下:我有一个模型对象的模型数组.我使用该对象设置标签和屏幕上的图像.地点图像存储在解析后端中,在我的附件中它是左上角的图像.我试图检索它并在左上角的图像中显示它.

在每个NSLog旁边,我有它正在构建的模型对象的代码,即'Di2zPyCmn8'.那是一个模型对象id.

从我的日志记录中,您可以看到单元格在一切完成之前返回.这是有意义的,因为块是异步的.

任何人都可以提供一些帮助,以便我可以正确构建tableviews吗?

不正当行为是指我在Parse中的后端没有图像作为对象.tableview单元格图像(左上角)应为空白.有时候,可以在那里找到来自其他后端对象的随机图像.

我相信这与细胞的流动和早期恢复有关.

当我在后端有图像时,该图像按预期显示在地点图像视图(左上角)中.

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


    static NSString *CellIdentifier = @"Cell";

    BIDActiveDealCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[BIDActiveDealCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    //get model object from array and use it's properties to populate the fields from CustomCell.h
    if ([self.activeDealModelArray count] == 0) {
        cell.descriptionLabel.text = @"Array count is 0";

    }else{
BIDActiveDealModel *dealActiveModel = [[BIDActiveDealModel alloc]init];
        dealActiveModel = self.activeDealModelArray[indexPath.row];

    NSLog(@"cellforRow - start of else : %@", dealActiveModel.placeObjectId);
    cell.descriptionLabel.text = dealActiveModel.dealTitleModel;//Puts title field. Called description as too lazy to go back and change
    cell.dealPlaceNameLabel.text = dealActiveModel.placeDescription;
    //cell.dealPlaceImageView.image = dealActiveModel.placeImage;
    cell.dealImageView.image = dealActiveModel.dealImageModel;//Sets deal image
    cell.dealDescriptionLabel.text = dealActiveModel.dealDescriptionModel;
    NSLog(@"cellforRow - end of else : %@", dealActiveModel.placeObjectId);

    //Use placeObjectID (foreign key) to get that place from linkedBusinessParseClass. Then get image for that class.
    PFQuery *query = [PFQuery queryWithClassName:@"linkedBusinessParseClass"];
    NSLog(@"cellforRow - after pfQuery : %@", dealActiveModel.placeObjectId);
    [query getObjectInBackgroundWithId:dealActiveModel.placeObjectId block:^(PFObject *placeImageObject, NSError *error) {
        NSLog(@"cellforRow - start geObjectInBackground : %@", dealActiveModel.placeObjectId);
        if (!error) {
            PFFile *imageFile = [placeImageObject objectForKey:@"image"];
            [imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
                NSLog(@"cellforRow - start getDataInBackground (Image) : %@", dealActiveModel.placeObjectId);
                if (!error) {
                    UIImage *image = [UIImage imageWithData:data];
                    cell.dealPlaceImageView.image = image;
                }
                NSLog(@"cellforRow - end getDataInBackground (Image) : %@", dealActiveModel.placeObjectId);
            }];
        }
        NSLog(@"cellforRow - end geObjectInBackground : %@", dealActiveModel.placeObjectId);
    }];//end of query
}//end of else that checks array count is 0
NSLog(@"Absolute end - return cell");
return cell;


    Logging:
 cellforRow - start
 of else : Di2zPyCmn8
 cellforRow - end of else : Di2zPyCmn8
 cellforRow - after pfQuery : Di2zPyCmn8
 Absolute end - return cell
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Cou*_*per 7

这是一个常见的错误.当你更努力地找到相关的帖子时,你可以在SO上找到很多关于这个问题的信息.

基本上,您的完成块捕获单元格对象的引用.但是,当最终执行完成块时,该单元在此期间已被重用.因此,访问它并可能将图像分配给单元格的视图元素是徒劳的(至少),因为单元格不再是单元格,因为块块捕获了单元格.

您应该与块一起捕获的是indexPath,然后在块中通过发送表视图来检索此indexPath的单元格cellForRowAtIndexPath:,以便在需要获取正确的单元格:

在完成块中:

所以,而不是:

cell.dealPlaceImageView.image = image;
Run Code Online (Sandbox Code Playgroud)

使用

BIDActiveDealCell* theCell = (BIDActiveDealCell*)[tableView cellForRowAtIndexPath:indexPath];
theCell.dealPlaceImageView.image = image;
Run Code Online (Sandbox Code Playgroud)

注意: 如果单元格theCell不再可见,表格视图将返回nil- 并且没有任何不良情况发生(尽管您的代码中存在一些其他问题,但这不会解决它们).

编辑:可能的改进/问题:

  • 不要在辅助线程上调用消息给UIKit对象 - 仅限主线程
  • 当有一个具有相同URL的待处理请求时,请避免启动请求
  • 利用图像缓存(尽管系统会在某种程度上这样做)
  • 使用占位符来获取最终设置的对象(图像)