2009-11-15 30 views
1

我一直在繪製自定義表格單元格(使用蘋果的樣本作爲基礎),現在必須做一個顯示來自URL的圖像的單元格 - 每個單元格將具有不同的圖像(基於某些數據它有),但所有的單元格是相同的,所以相同的重用ID。iPhone自定義繪製的UITableViewCell,如何加載+插入網頁中的圖像在線程中?

這樣做的正確結構是什麼?很明顯,我需要在新線程中加載圖像。我有以下功能到目前爲止坐在細胞查看它在自己的線程運行的類:


- (void)loadImage 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    self.img = [UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: [myProduct objectForKey:@"ImagePath"]]]]; 
    [self setNeedsDisplay]; 
    [pool release]; 
} 
 

當我把這個從drawRect中函數本身(這是壞的),那麼它「作品」,但每當發生任何事情時(選擇等),這顯然都會被調用。如果我把它放在單元格uiview的init函數中,那麼它只會被前面8個單元調用,然後它們會被重用。其他的變化最終導致圖像在重用時沒有得到「重置」,所以相同的8張圖像在表格中重複(儘管其他文本更新)。

我暫時不擔心緩存,但是有沒有關於如何做到這一點的任何示例,或者任何人都可以指向正確的方向?謝謝。

回答

0

那麼,當您將單元出列時,您可以強制加載圖像。您不必到init內做到這一點......通常這樣做:

cell = dequeueCell... 
if (!cell) { 
    //create one 
} 

return cell; 

你可以做的是恢復單元之前,您可以強制圖像加載,如果它是你想要的細胞類型。這樣,無論何時顯示,您都可以從緩存中抓取它(如果存在),如果不存在,請訪問網站。

+0

我該如何處理線程位?我可以調用cellforrowatindexpath中的線程去獲取圖像,但是在那個時候,細胞已經繪製了自己(減去圖像),然後我需要再次在細胞視圖上調用setNeedsDisplay? – Tom 2009-11-15 17:49:23

2

該解決方案將不得不更復雜,因爲默認情況下,UITableView回收單元格(當一個滾動頂部時,它將移動到底部並用新數據重新配置)。因此,您可能會開始下載圖像,但在下載完成之前單元格的內容已更改。

cellForRowAtIndexPath:,你應該從緩存(你的myProduct對象,一個NSArray,無論)中獲取圖像。如果它不在那裏,你應該檢查一個標誌,看看它是否已經被加載。如果它尚未被加載,那麼你設置該標誌並分離一個新線程(你應該看看NSOperation,它會排隊工作,並保護你一次啓動太多的線程)。

在你的線程中,你應該下載圖像,然後使用performSelectorOnMainThread:target:waitUntilDone:在圖像的主線程上調用一個方法。該方法可以更新緩存,將isLoading標誌設置爲NO,並更新單元。這樣做很重要,因爲Cocoa要求您的所有UI更新代碼都在主線程中。

我希望這是一個有用的提綱。

+0

謝謝,這有助於。我看了一下stanford系列的線程flickr tableview代碼,它幫助了我。目前通過執行cell.image = [cachedImg:url],然後觸發NSOperation,然後執行一個reloadData tableview完成後,但我很想使用自定義繪圖與其他單元格一樣 - 我會怎麼做呢? 我需要將圖像傳遞給單元類,它將其傳遞給它的視圖類,然後調用setNeedsDisplay?我如何引用由performSelectorOnMainThread調用的方法中的原始單元格? – Tom 2009-11-15 20:27:31

+1

我發現一個非常好的方法是將NSOperations與NSNotifications結合使用 - 您可以讓一個單元格訂閱圖像加載通知,從而完全加載圖像。您可以附加像圖像URL之類的東西,以確保您獲取的通知與您正在等待的圖像相關,並在prepareForReuse中取消訂閱,以便在發送通知時僅更改可見單元格。 – 2009-11-15 20:52:15

1

如果您還沒有看到明確的文檔從蘋果到UIImage的是線程安全的我不效應我認爲你應該這樣做。取而代之的是將你的圖像作爲NSData,並在主線程中將其轉換爲UIImage。基本規則是所有UIKit工作必須在主線程中完成,否則行爲未定義。

相關問題