我正在创建一个应用程序,允许您浏览网站上的图片。我目前正在使用以下方式下载图像:
UIImage *myImage = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]]];
效果很好,但可能很耗时。我开始下载20张图片,但是在下载所有图片30秒左右之后我才能做任何事情。
这一次等待并不是那么糟糕,但如果我想下载第二十四张图像,我将不得不再等30秒。
基本上,有没有一种方法可以一次下载这些图像而不用我的任何动画?
感谢。
答案 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)
虽然在后台线程上加载图像绝对是解决方案,但我会使用NSOperation和NSOperationQueue而不是自己处理线程(这是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处理或错误或完成。 您还可以使用自动释放的对象,但就性能而言,我喜欢在没有自动释放的对象的情况下使用它。