2011-05-31 70 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是无关紧要在这种情况下,它的首选形式说是。

当你有时髦的细胞行为时,怀疑的另一个问题是如果你正确地处理细胞再利用。你没有向我们展示那些代码,所以我们不能说。如果您保留对某个单元格的引用,并将图像数据设置为该单元格,那么当表格将单元格从您下方重新使用时,您会自己填满该单元格。 (我不认为这是这种情况下的问题。)