0

我正在尝试构建一个很好的功能来访问网络以获取图像,如果在网络上找到它们,我会将它们存储在我制作的缓存系统中。如果图像已经存储在缓存中,我会返回它。如果图像在缓存中,则调用该函数getImageFromCache并返回图像,否则,它将进入网络并获取。

代码可能如下所示:

UIImageView* backgroundTiles = [[UIImageView alloc] initWithImage[self getImageFromCache:@"http://www.example.com/1.jpg"]];

现在,由于网络流量的延迟很大,我将继续使用线程。所以我希望图像在我从网络上得到结果之前显示一个临时图像。

我想知道的是如何跟踪这么多被顺序访问的图像,被UIImageView这个函数(getImageFromCache)添加到s。

有些东西在那里行不通:

-(UIImage*)getImageFromCache:(NSString*)forURL{

    __block NSError* error = nil;
    __block NSData *imageData;
    __block UIImage* tmpImage;

    if(forURL==nil) return nil;

    if(![self.imagesCache objectForKey:forURL])
    {
        // Setting a temporary image until we start getting results
        tmpImage = [UIImage imageNamed:@"noimage.png"];

        NSURL *imageURL = [NSURL URLWithString:forURL];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
            imageData = [NSData dataWithContentsOfURL:imageURL options:NSDataReadingUncached error:&error];
            if(imageData)
            {
                NSLog(@"Thread fetching image URL:%@",imageURL);
                dispatch_async(dispatch_get_main_queue(), ^{
                    tmpImage = [UIImage imageWithData:imageData];
                    if(tmpImage)
                    {
                        [imagesCache setObject:tmpImage forKey:forURL];
                    }
                    else
                        // Couldn't build an image of this data, probably bad URL
                        [imagesCache setObject:[UIImage imageNamed:@"imageNotFound.png"] forKey:forURL];
                   });
            }
            else
                // Couldn't build an image of this data, probably bad URL
                [imagesCache setObject:[UIImage imageNamed:@"imageNotFound.png"] forKey:forURL];

        });

    }
    else
        return [imagesCache objectForKey:forURL];

    return tmpImage;
}
4

3 回答 3

1

这不是您问题的直接答案,但您是否知道不需要使用 GCD 异步下载内容(在后台线程上)?只需使用 NSURLConnection 及其委托方法。您的所有代码都将在主线程上,但实际的连接和下载将在后台进行。

(事实上​​,我已经编写了一个类 MyDownloader,它会为您处理所有这些:

http://www.aeth.com/iOSBook/ch37.html#_http_requests

向下滚动到有关 MyDownloader 及其子类 MyImageDownloader 的部分,这正是您需要在此处完成的事情。此外,请注意该章中的后续代码显示如何在下载完成时使用通知,提示需要这些图像的表视图重新加载包含图像刚刚到达的图像视图的行。)

于 2013-05-06T17:30:42.443 回答
1

从头开始构建它很好,但如果你想保存所有工作,替换SDWebImage库有一个下降,它支持来自网络的远程图像,并具有所有功能,如临时图像、异步加载、缓存等,你说你需要

于 2013-05-07T08:58:42.907 回答
0

在您的后台线程中,一旦下载完成并将图像保存到缓存中,我建议您使用NSNotificationCenter发布通知,让应用程序的其他部分知道缓存已更新。

这假定应用程序管理图像视图的任何部分都已使用该addObserverForName方法注册其对这些通知的兴趣。当它收到这样的通知时,它可以尝试再次从缓存中检索图像并在适当的情况下更新其图像视图。

根据图像视图的数量,您可能希望以某种方式(例如在userInfo字典中)通过通知中的图像 url,然后基于此决定应该刷新哪些图像视图,而不是全部刷新它们。

我应该补充一点,我还建议摆脱内部dispatch_async调用。没有必要这样做,尽管您可能需要向缓存对象添加同步,以便可以从主线程和下载线程安全地访问它。

于 2013-05-06T21:14:52.497 回答