如何在不举起其他内容的情况下下载图像?

时间:2010-03-03 04:10:32

标签: iphone objective-c uiimage

我正在创建一个应用程序,允许您浏览网站上的图片。我目前正在使用以下方式下载图像:

 UIImage *myImage = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]]];

效果很好,但可能很耗时。我开始下载20张图片,但是在下载所有图片30秒左右之后我才能做任何事情。

这一次等待并不是那么糟糕,但如果我想下载第二十四张图像,我将不得不再等30秒。

基本上,有没有一种方法可以一次下载这些图像而不用我的任何动画?

感谢。

3 个答案:

答案 0 :(得分:8)

当然,将下载任务放在一个线程中,并使用回调让您的程序知道每个图像何时完成。然后,您可以在完成加载时绘制图像,而不是占用应用程序的其余部分。 This link有一个模板,您可以将其用作示例。

这是一个快速而肮脏的例子:

- (void)downloadWorker:(NSString *)urlString
{
    NSAutoreleasePool *pool  = [[NSAutoreleasePool alloc] init];
    NSURL             *url   = [NSURL URLWithString:urlString];
    NSData            *data  = [NSData dataWithContentsOfURL:url];
    UIImage           *image = [[UIImage alloc] initWithData:data];

    [self performSelectorOnMainThread:@selector(imageLoaded:) 
                           withObject:image
                        waitUntilDone:YES];
    [image release];
    [pool drain];
}

- (void)downloadImageOnThread:(NSString *)url
{
    [NSThread detachNewThreadSelector:@selector(downloadWorker:) 
                             toTarget:self 
                           withObject:url];
}

- (void)imageLoaded:(UIImage *)image
{
    // get the image into the UI
}

为您要加载的每个图片调用downloadImageOnThread,每个图片都会获得自己的主题,并且每个完成时都会调用imageLoaded

答案 1 :(得分:3)

虽然在后台线程上加载图像绝对是解决方案,但我会使用NSOperationNSOperationQueue而不是自己处理线程(这是Apple建议处理的方式)像这样穿线问题!)

NSOperationQueue将很好地处理启动/停止线程,您可以选择一次运行多少等等。它基本上与其他答案相同,但您可以获得更多控制权。

tutorial here看起来很不错。

答案 2 :(得分:1)

是的,你可以使用辅助线程,并做很多工作或者你可以使用苹果给我们的东西。

NSURLDownload,不会“滞后”您的主线程,您使用方法生成它并设置endSelector,下载完成后将调用endSelector。 为此产生一个辅助线程并不是你应该做的。

在这里你从我的应用程序中获得了一些代码,它可以完美地工作,而不会给一个厄运的沙滩球。

- (void)downloadAvatar:(NSString *)URL{
 NSURL *url = [[NSURL alloc] initWithString:URL];
 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
 [url release];
 NSURLDownload *download = [[NSURLDownload alloc] initWithRequest:request delegate:self];
 NSString *path = [[NSString alloc] initWithFormat:@"%@data/%@.jpg",[[BFAppSupport defaultSupport] bfFolderPath],[[xfSession loginIdentity] userName]];
 [download setDestination:path allowOverwrite:YES];
 [download release];
 [path release];
 [request release];
}
- (void)downloadDidFinish:(NSURLDownload *)download{
 NSString *path = [[NSString alloc] initWithFormat:@"%@data/%@.jpg",[[BFAppSupport   defaultSupport] bfFolderPath],[[xfSession loginIdentity] userName]];
 NSData *imageData = [[NSData alloc] initWithContentsOfFile:path];
if( [imageData length] < 10 ){
  [self performSelector:@selector(downloadAvatar:) withObject:@"http://media.xfire.com/xfire/xf/images/avatars/gallery/default/xfire160.jpg" afterDelay:0.0];
  [imageData release];
  [path release];
  return;
}
NSImage *theImage = [[NSImage alloc] initWithData:imageData];
[imageData release];
[path release];
[yourImage setImage:theImage];
[theImage release];
}

- (void)download:(NSURLDownload *)aDownload didFailWithError:(NSError *)error{
 NSLog(@"Avatar url download failed");
}

代码有点难看,但不难改变它,因为你得到了你需要的3件事,启动下载的方法和2处理或错误或完成。 您还可以使用自动释放的对象,但就性能而言,我喜欢在没有自动释放的对象的情况下使用它。