如何在iOS中从一系列网址预加载图像?

时间:2014-01-12 04:45:23

标签: ios objective-c

我有一个音乐应用程序,我想预先加载专辑艺术。现在,当您点击下一首歌时,它会从一个URL加载专辑封面,但如果它已经预先加载并且在内存中会很好。我尝试了一些东西,但似乎没有什么工作真的有用。有没有人知道一种技术,我可以在iOS中预加载图像,然后在以后查找该图像,如果它不存在,那么下载它?

使用更多细节进行编辑......

当我在我的应用程序上播放“电台”时,我向服务器发出请求,该服务器返回播放列表的JSON。这个JSON的内部是每首歌曲以及包括专辑封面URL的数据。当用户去播放“电台”时,我想预先加载图片中的下一个专辑封面图片或整个播放列表中的所有专辑封面网址。

无论如何,我尝试在后台加载UIImage中的下一个专辑封面网址,就像temporaryAlbumArt一样,然后播放下一首歌时只需albumArt = temporaryAlbumArt然后重复进程设置接下来的歌曲专辑艺术到临时等等。

我尝试过这样的事情:

if (temporaryAlbumArt) {
  albumArt = temporaryAlbumArt
} else {
  albumArt = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:firstAlbumArtURL]]];
}

temporaryAlbumArt = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:nextAlbumArtURL]]];

我想我的问题是,最好的方法是什么:

  • 将图像或多个图像从URL加载到内存
  • 稍后使用这些图像,没有任何延迟时间

4 个答案:

答案 0 :(得分:1)

您可以使用此“必备”工具APSmartStorage。它支持您需要的一切。

答案 1 :(得分:0)

我不确定你要问的是什么,但是如果你知道下一首歌将会是什么,你只能在后台线程中加载它,然后在下一首歌开始时准备好显示它? / p>

如果您希望应用程序在本地存储所有下载的图像,您最终可能遇到空间问题,但它可以。您可以使用下载的图像然后将其存储在缓存目录中(不是文档目录或Apple会生气!)。当一首歌来时,只需快速检查图像,如果不是本地下载它。歌曲需要几分钟,所以应该有时间在后台完成所有这些。

#define GET_QUEUE dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

// while song is playing...
dispatch_async(GET_QUEUE, ^{
  // On a separate thread look for the image locally in the cache and then
  // download it if necessary
});

我不确定这是否能回答你的问题......

好的,所以这里有更多代码 - 基本上它让我在上下文中提出有希望的有用问题。

// Inside some loop/method that plays songs...
if (temporaryAlbumArt)
  albumArt = temporaryAlbumArt
else
  albumArt = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:firstAlbumArtURL]]]; 
  // If this keeps executing then perhaps temporaryAlbumArt is getting released somehow?
  // Are you persisting it correctly through each iteration/method call?

// show art...
// start music    

// Call art update
dispatch_async(GET_QUEUE, ^{
  temporaryAlbumArt = nil; // In case the data hasn't been obtained yet on the next iteration???
  temporaryAlbumArt = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:nextAlbumArtURL]]]; 
  // This works ok then? Can you make sure this is completing correctly before the next iteration/method call?
});    

抱歉,我无法提供更多帮助。

答案 2 :(得分:0)

此库可满足您的需求:JMImageCache

循环浏览您的URL,通过JMImageCache下载它们,当您需要显示图像时,如果已完成下载,库将获取存储的图像。

//You can do this when you get the array of urls to download the images in the background
for(NSURL *url in urls) {
    [[JMImageCache sharedCache] imageForURL:url];
}

//and then when you need an image:
[imageView setImageWithURL:url placeholder:[UIImage imageNamed:@"placeholder.png"]];

答案 3 :(得分:0)

我已编写此代码以从服务器下载数据并将该数据保存到文档目录中,以便下次有人点击同一个网址时,会从文档目录中获取该数据,而不会有任何服务器命中。

-(void)downloadImageForProductsFromArray:(NSArray *)inventoryArr {
BOOL isAllDataDownloaded = YES;
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = @"Data Sync...";
[[NSOperationQueue mainQueue] addObserver:self forKeyPath:@"operations" options:0 context:nil];
for (int i = 0; i < inventoryArr.count; i++) {
    NSString *productUrlStr = [inventoryArr objectAtIndex:i];
    NSData *dirData = [CommonUtils fetchImageDataFromDirectoryWithImageName: productUrlStr];/*****Check whether Image data is already downloaded and saved in document directory*****/
    if (!dirData) {
        isAllDataDownloaded = NO;

        NSBlockOperation *downloadImgOpr = [[NSBlockOperation alloc] init];
        downloadImgOpr.queuePriority = NSOperationQueuePriorityVeryHigh;
        downloadImgOpr.qualityOfService = NSQualityOfServiceUserInitiated;

        [downloadImgOpr addExecutionBlock:^{
            NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString: productUrlStr]];
            if (imageData) {

                /*****Save Image Data in Document Directory*****/
            }
        }];

    } 
}
if (isAllDataDownloaded) {
    [MBProgressHUD hideAllHUDsForView:self.view animated:YES];
}}

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                     change:(NSDictionary *)change context:(void *)context{
if (object == [NSOperationQueue mainQueue] && [keyPath isEqualToString:@"operations"]) {
    if ([[NSOperationQueue mainQueue].operations count] == 0) {
        // Do something here when your queue has completed
        [MBProgressHUD hideAllHUDsForView:self.view animated:YES];

        NSLog(@"queue has completed");
    }
}
else {
    [super observeValueForKeyPath:keyPath ofObject:object
                           change:change context:context];
}

}

在此代码中,我拥有库存数组中的所有url字符串。在for循环中,我已经进行了多次操作并将这些操作添加到队列中(我使用主队列来保存UI并同步数据。选择你的适当排队)。此外,我已将KVO添加到队列中以获取键路径值“operations”,这样如果操作计数为0,我们就可以执行有用的操作。