2011-05-31 69 views
0

我正在試圖將favicons合併到UITableView中。該表基本上提取網站,我想在右側顯示favicon。最初,我在右側放置了一個佔位符圖標,並讓後臺運行一個函數。該功能採用網站的URL,解析並嘗試查找網站圖標。如果找不到,它會保留相同的佔位符圖像;否則,它會用該網站的圖標替換它。我最初嘗試使用[tableView reloadData],它在模擬器中運行良好,但它確實有些奇怪和不可靠的事情(例如,它會創建一些單元格,但留下一個巨大的空單元格)。無論如何,我偶然發現了reloadRowsAtIndexPaths,它看起來像我需要使用的函數。但是,結果仍然非常不可靠。我有我的抓取功能在後臺運行,這樣:reloadRowsAtIndexPaths停止加載UITableViewCells?

在FetchFaviconWrapper
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
...//other code here for showing website labels 

    //obtain the favicon.ico 
if(!this_article.iconLoaded){ 
    this_article.iconLoaded = TRUE; 
    NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys:this_article, @"article", indexPath, @"indexPath", nil]; 
    [self performSelectorInBackground:@selector(fetchFaviconWrapper:) withObject:args]; 
} 

cell.favicon.image = this_article.icon; 

return cell; 
} 

- (void)fetchFaviconWrapper:(NSDictionary *)args { 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
[self fetchFavicon:[args objectForKey:@"article"]]; 
NSArray *paths = [NSArray arrayWithObject:[args objectForKey:@"indexPath"]]; 
[articleTable beginUpdates]; 
[articleTable reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade]; 
[articleTable endUpdates]; 
[pool release]; 
} 

基本上,fetchFavicon需要一個網站,需要主機URL,追加 「/favicon.ico」,構建它變成一個NSData對象,並找到圖像(如果它存在)。但是,這也相當不可靠。在後臺運行線程時替換佔位符圖像的最佳方式是什麼?我可以在主線程上做所有事情,但這隻會讓桌面加載速度變慢。似乎有些東西是我忽略的,或者是我忘記添加的東西......只是無法弄清楚。

回答

1

如果您是從單獨的線程訪問和修改您的用戶界面並不完全清楚。

如果是這樣,這是你不可靠的原因。 UIKit只能從主線程訪問。如果你有興趣,你會在S.O上找到很多問題。並在網上進行了許多討論。

有一個解決方法,如果你想保持你的第二個線程。事實上,您可以使用以下方式將消息發送到您的UI對象:

-performSelectorOnMainThread:withObject:waitUntilDone: 

而不是直接從輔助線程發送它們。

如果此解決方法不能解決您的問題,那麼我會建議重新設計您的應用程序,以便輔助線程只訪問您的模型,而無需訪問用戶界面。所有修改UI的操作都應該在主線程上執行。如果您需要在模型準備就緒時在桌面上撥打reloadData,則可以使用performSelectorOnMainThread:withObject:waitUntilDone來完成。

+0

是的,我試過了,但我幾乎得到了同樣的東西。儘管我注意到,如果我向下滾動,那麼最初沒有顯示的網站(如第5-6頁)會在我下樓時重新加載。所以,我猜這只是第一個有問題的6個人。但爲什麼會有這種行爲?此外,我意識到,按下時已正確重新加載動畫的單元格(在突出顯示時變爲藍色),以及沒有正確動畫的單元格。 – SpacePyro 2011-05-31 21:33:04

+0

只是一個問題:你是從輔助線程修改UI(使用UIKit)嗎? – sergio 2011-05-31 21:45:39

+0

那麼,我設置了(如果我沒記錯的話)是我有網站通過performSelectorInBackground獲取。在fetcher函數結束時,我有'[articleTable reloadData]'。我不知道是否會擾亂任何東西,但我想所有這些都在後臺的獨立線程中運行。當'cellForRowAtIndexPath'被調用時,以及何時需要找出顯示哪個圖標,它會啓動一個額外的線程(如上面在原始文章中所述)。 – SpacePyro 2011-05-31 21:50:05

0

我會建議一些事情。

  1. 附加./favicon.ico並不總是準確的。研究各種向網站添加網站圖標以支持網站的方法。

  2. 至於替換默認的佔位符,我建議使用NSNotificationCenter通知主線程何時進行更改。

+0

它不僅僅是附加favicon.ico;我只是略去了大部分的細節,因爲它不是很相關。 – SpacePyro 2011-05-31 22:28:40

0

我絕對重申沒有來自後臺線程的用戶界面。

更改初始代碼:

- (void)fetchFaviconWrapper:(NSDictionary *)args { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    [self fetchFavicon:[args objectForKey:@"article"]]; 
    NSArray *paths = [NSArray arrayWithObject:[args objectForKey:@"indexPath"]]; 

    [articleTable beginUpdates]; 
    [articleTable reloadRowsAtIndexPaths:paths 
         withRowAnimation:UITableViewRowAnimationFade]; 
    [articleTable endUpdates]; 

    [pool release]; 
} 

到這一點,看看您是否仍然有問題

- (void)fetchFaviconWrapper:(NSDictionary *)args { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    [self fetchFavicon:[args objectForKey:@"article"]]; 
    NSArray *paths = [NSArray arrayWithObject:[args objectForKey:@"indexPath"]]; 

    [self performSelectorOnMainThread:@selector(reloadData) 
         withObject:nil 
         waitUntilDone:YES]; 

    [pool release]; 
} 

的waitUntilDone是無關緊要在這種情況下,它的首選形式說是。

當你有時髦的細胞行爲時,懷疑的另一個問題是如果你正確地處理細胞再利用。你沒有向我們展示那些代碼,所以我們不能說。如果您保留對某個單元格的引用,並將圖像數據設置爲該單元格,那麼當表格將單元格從您下方重新使用時,您會自己填滿該單元格。 (我不認爲這是這種情況下的問題。)