UIImages NSURL和线程

时间:2013-05-06 17:17:27

标签: ios multithreading cocoa-touch uiimageview uiimage

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

代码可能如下所示:

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

现在,我正在继续使用线程,因为网络流量导致了很大的延迟。所以我希望图像在我从网络上获得结果之前显示临时图像。

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

某些东西在那里不起作用:

-(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;
}

3 个答案:

答案 0 :(得分:1)

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

(事实上,我已经写了一个课程,MyDownloader,它会照顾你所有这些:

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

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

答案 1 :(得分:1)

从头开始构建它很好但是如果你想保存所有的工作,那么替换SDWebImage库中有一个支持来自网络的远程图像,并具有像Temp Image这样的所有功能,Asychronous Loading,Caching等,你说你需要

答案 2 :(得分:0)

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

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

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

我应该补充一点,我还建议删除内部dispatch_async调用。虽然您可能需要向缓存对象添加同步,但是可以从主线程和下载线程安全地访问它,因此不需要这样做。