Parse PFFile download order iOS

*爱你&永不变心* 提交于 2019-12-11 02:44:14

问题


I'm storing 5 PFFiles in an array and using getDataInBackgroundWithBlock to download those files from Parse.

The problem is the order at which they appear in the table view cells is different every time, presumably because the files are download at different speeds due to the different file sizes.

for (PFFile *imageFile in self.imageFiles) {
  [imageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
    if (!error) {
      UIImage *avatar = [UIImage imageWithData:imageData];
      [self.avatars addObject:avatar];
      cell.userImageView.image = self.avatars[indexPath.row];
    }
  }];
}

The self.imageFiles array is in the correct order. How do I ensure that the images downloaded are added to the self.avatars array in the same order as the self.imageFiles?


回答1:


The question has two parts: (1) explicitly, how to maintain the order of results of asynchronous operations, (2) implied by the use of cell, how to properly handle asynch requests in support of a tableview.

The answer to the first question is simpler: keep the result of the request associated with the parameter for the request.

// change avatars to hold dictionaries associating PFFiles with images
@property(nonatomic,strong) NSMutableArray *avatars; 

// initialize it like this
for (PFFile *imageFile in self.imageFiles) {
    [avatars addObject:[@{@"pfFile":imageFile} mutableCopy]];
}

// now lets factor an avatar fetch into its own method
- (void)avatarForIndexPath:(NSIndexPath *)indexPath completion:^(UIImage *, NSError *)completion {

    // if we fetched already, just return it via the completion block
    UIImage *existingImage = self.avatars[indexPath.row][@"image"];
    if (existingImage) return completion(existingImage, nil);

    PFFile *pfFile = self.avatars[indexPath.row][@"pfFile"];
    [pfFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
        if (!error) {
            UIImage *avatar = [UIImage imageWithData:imageData];
            self.avatars[indexPath.row][@"image"] = avatar;
            completion(avatar, nil);
        } else {
            completion(nil, error);
        }
    }];
}

Okay for part (1). For part 2, your cellForRowAtIndexPath code must recognize that cells are reused. By the time the asynch image fetch happens, the cell you're working on might have scrolled away. Fix this by not referring to the cell in the completion block (only the indexPath).

    // somewhere in cellForRowAtIndexPath
    // we're ready to setup the cell's image view 

    UIImage *existingImage = self.avatars[indexPath.row][@"image"];
    if (existingImage) {
        cell.userImageView.image = existingImage;
    } else {
        cell.userImageView.image = // you can put a placeholder image here while we do the fetch
        [self avatarForIndexPath:indexPath completion:^(UIImage *image, NSError *error) {
            // here's the trick that is often missed, don't refer to the cell, instead:
            if (!error) {
                [tableView reloadRowsAtIndexPaths:@[indexPath]];
            }
        }];
    }

Reloading the row in the completion block will cause cellForRowAtIndexPath to be called again, except on that subsequent call, we'll have an existing image and the cell will get configured immediately.




回答2:


Whilst danh's answer has answered my question, I did manage to solve it shortly after posting the question. I'm capturing the index of each imageFile and making sure they are added to the self.avatars array in that order.

for (PFFile *imageFile in self.imageFiles) {
  NSInteger index = [self.imageFiles indexOfObject:imageFile];
  [imageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
    if (!error) {
      UIImage *avatar = [UIImage imageWithData:imageData];
      self.avatars[index] = avatar;
      [self.tableView reloadData];
    }
  }];
}

Then cell.userImageView.image = self.avatars[indexPath.row]; in cellForRowAtIndexPath:



来源:https://stackoverflow.com/questions/29867837/parse-pffile-download-order-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!