使用GCD下载图像的UIImageView类别失败,大量同时下载

时间:2014-10-20 22:39:28

标签: objective-c uiimageview grand-central-dispatch

我已经使用AFNetworking在我的项目中下载和缓存图像,但我想用最轻的内部类别替换框架,显然我在调度队列中面临很多问题,而且我有很难调试它们。

这是我现在正在使用的category,对于少量同时下载没有任何问题,但是,如果我开始大量下载,它看起来像应用程序挂起了无穷无尽的负载。

我需要一些帮助调试,我想了解我在这里缺少的东西。

以下是两个主要功能:

- (void) imageWithUrl: (NSURL*) imageUrl placeHolderImage: (UIImage *) placeHolderImage shouldAlwaysRefresh: (BOOL) shouldRefresh {

    self.image= placeHolderImage;

    TMCache *sharedCache = [TMCache sharedCache];
    [sharedCache trimToDate: [NSDate dateWithTimeIntervalSinceNow: -(60.0*24.0*7.0)]];

    UIImage *cachedImage = [sharedCache objectForKey: [imageUrl absoluteString]];

    if(cachedImage){
        self.image = cachedImage;

        if(shouldRefresh)
            [self fetchImageFromUrl: imageUrl];
    }
    else{
        [self fetchImageFromUrl: imageUrl];
    }
}

- (void) fetchImageFromUrl: (NSURL *) imageUrl{

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

    dispatch_async(queue, ^{

        NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];

        UIImage *image = [UIImage imageWithData:imageData];

        if(image){

            [[TMCache sharedCache] setObject:image forKey: [imageUrl absoluteString]];

            dispatch_sync(dispatch_get_main_queue(), ^{
                self.image = image;
            });


        }
    });

}

1 个答案:

答案 0 :(得分:0)

您的问题很可能是dispatch_sync返回主队列,在图片加载完成后创建deadlock

解决这个问题最简单的方法就是将dispatch_sync替换为dispatch_async

if(image) {
    [[TMCache sharedCache] setObject:image forKey: [imageUrl absoluteString]];

    dispatch_async(dispatch_get_main_queue(), ^{
        self.image = image;
    });
}

我没有看到任何理由使用dispatch_sync,因为您已经在dispatch_async区块内;这不应该对您的代码产生任何负面影响。事实上,如果可能的话,通常应该尽量避免使用dispatch_sync,这恰恰是针对您在此处运行的问题。


旁注: AFNetworking实际上为您提供了相当多的代码。在使用自己的解决方案而不是AFNetworking之前,我会认真考虑三次。