2010-03-03 84 views
2

我正在製作一個應用程序,允許您瀏覽網站上的圖片。我目前正在使用下載圖像:如何在不阻礙其他情況下下載圖像?

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

它工作很好,但可能很費時。我從下載20張圖像開始,但在完成下載所需的30秒後,我無法做任何事情。

這一次等待並不是那麼糟糕,但如果我想下載第21 - 40張圖像,我將不得不再等待30秒。

基本上,有沒有一種方法可以一次下載這些圖像,而不會阻止我的任何動畫?

謝謝。

回答

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

+0

對不起,但我不確定你是什麼意思或我該怎麼做。你能再解釋一下嗎? – androidnotgenius 2010-03-03 04:24:39

+0

@pureman,你看到鏈接了嗎?這非常簡單 - 您使用'[NSThread detachNewThreadSelector ...]'創建一個具有特定方法的線程,然後在worker線程完成時使用'performSelectorOnMainThread'回調應用程序。 – 2010-03-03 04:32:59

+0

我會在我的答案中添加一些代碼以清除它。 – 2010-03-03 04:34:51

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"); 
} 

的代碼是醜了一點,但它不是很難改變它,你得到了你所需要的三兩件事,即開始下載和2處理或錯誤,或完成的方法。 您還可以使用更多的自動釋放對象,但就性能而言,我喜歡在不使用自動釋放對象的情況下使用它。

3

雖然在後臺線程加載圖像是肯定的解決方案,我會使用和處理的線程的NSOperationNSOperationQueue,而不是你自己(這是蘋果推薦對付這樣的線程問題的方式!)

NSOperationQueue將很好地處理啓動/停止線程,您可以選擇一次運行多少個等等。它基本上與其他答案相同,但您可以獲得更多的控制權。

有一個tutorial here,看起來不錯。

相關問題