【问题标题】:iOS - Downloading images asynchronously and using them alongside Core DataiOS - 异步下载图像并将它们与 Core Data 一起使用
【发布时间】:2014-04-07 15:42:22
【问题描述】:

在我的核心数据模型中,我有一个保存图像 URL 的实体。我想下载这些图像,以便可以在我的 UICollectionView 模型中使用它们,这是我的核心数据实体的数组。我希望始终能够同步访问这些图像(假设它们已经异步下载),因此它们在各自的单元格中加载之间没有延迟。

目前,我在 UICollectionViewcellForIndexPath: 数据源委托方法中使用异步方法,但是当重新加载集合视图时,如果仍在下载图像,它们会被分配到错误的单元格作为单元格在此期间已插入。

这个问题看起来应该很容易解决,但我无法解决。

非常感谢任何想法。

谢谢。

【问题讨论】:

标签: ios objective-c asynchronous


【解决方案1】:

您可以在viewDidLoad中异步下载图片,并将它们添加到NSMUtableArray中,如下所示

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        for (int i = 0; i < carPhotos.count; i++) {

            NSURL *photoURL = [NSURL URLWithString:carPhotos[i]];
            NSData *photoData = [NSData dataWithContentsOfURL:photoURL];
            UIImage *image = [UIImage imageWithData:photoData];
            [carImages addObject:image];

            dispatch_async(dispatch_get_main_queue(), ^{
                [self.tableView reloadData];
            });

        }

    });

然后检查cellForRowAtIndexpath,确保indexPath与arrayIndex匹配,如果要为未加载的图片加载一个dummy image,如下:

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

{ 静态 NSString *CellIdentifier = @"Cell"; CarsAppCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; cell.carMakeLabel.text = carMakes[indexPath.row]; cell.carModelLabel.text = carModels[indexPath.row];

if (carImages.count > indexPath.row) {
    cell.carImage.image = carImages[indexPath.row];
} else {
    cell.carImage.image = [UIImage imageNamed:@"dummy.png"];
}

return cell;

}

希望对你有帮助……

【讨论】:

  • 这也是我最初的想法,但是我的 UICollectionView 使用了核心数据和加载的图像中的数据,因此存在两个数据不同步的危险。
【解决方案2】:

你可以做几件事:

  1. 在单元格的 prepareForReuse 中,您可以取消任何(仍然)待处理的图像请求。
  2. 在完成图像请求的过程中,您可以在设置图像之前验证图像 url 是否仍如预期。

类似:

-(void)prepareForReuse
{
    [super prepareForReuse];
    _imageUrl = nil;
}

-(void)useImageUrl:(NSString*)imageUrl 
{
    _imageUrl = imageUrl;
    if(_imageUrl)
    {
        __weak typeof(self) weak = self;

        [UIImage fetchRemoteImage:imageUrl completion:^(UIImage* image){
            if(weak.imageUrl && [weak.imageUrl isEqualToString:imageUrl] && image) {
                weak.imageView.image = image;
            }
        }];
    }
}

【讨论】:

  • 也许我很困惑,但是第一种方法是如何取消请求的呢?第二种方法虽然是个好主意:)
  • 这个实现没有实现#1,所以你不会感到困惑。
  • 它只是使用 prepareForReuse 来添加一点保护,防止图像开始设置错误。
  • 啊,好吧,为什么需要弱?我记得以前用过,但忘了为什么。
  • 在这种情况下,它并不是严格“需要”的,因为没有保留周期(单元格不会以某种方式保留对块的引用)但是,它将允许单元格在网络操作完成。
猜你喜欢
  • 1970-01-01
  • 2012-08-27
  • 2018-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-05
相关资源
最近更新 更多