延迟后如何在 tableView 中加载图像?

Posted

技术标签:

【中文标题】延迟后如何在 tableView 中加载图像?【英文标题】:How to load images in tableView after a bit of delay? 【发布时间】:2011-04-09 04:16:29 【问题描述】:

我见过一个叫 ZuluTrade 的应用,它的 tableView 单元格中有一个图表。

基本上好像是tableViewCell的imageView中的图片。

当页面加载时,tableView 首先显示文本,然后在我们滚动 tableView 时将图像加载到 tableViewCell 中。

这有助于提高性能,因为用户不必等到所有内容都加载到单元格中,并且它使 tableView 滚动平滑。

如何实现该功能?

以下是应用截图:

我的tableView中的代码cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

NSString *MyIdentifier = [NSString stringWithFormat:@"MyIdentifier %i", indexPath.row];

MyTableCell *cell = (MyTableCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
//if (cell == nil) 
    cell = [[[MyTableCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];


    NSString *testVal = [[NSUserDefaults alloc] valueForKey:@"idValue"];

    if (testVal == (NSString *)[NSNull null]) 
        testVal = @"NULL";
    
    //NSLog(@"testVal : %@",testVal);
NSLog(@"Fund Name : %@",[[array1 objectAtIndex:indexPath.row] valueForKey:@"FundName"]);

    NSDate *date = [NSDate date];
NSDateFormatter *dtFormat = [[NSDateFormatter alloc] init];
[dtFormat setDateFormat:@"yyyy-MM-dd"];
NSString *dtString = [dtFormat stringFromDate:date];

  NSString *fundname = [NSString stringWithFormat:@"%@",[[array1 objectAtIndex:indexPath.row] valueForKey:@"FundName"]];


NSString *imageName =[NSString stringWithFormat:@"%@_%@.png",fundname,dtString]; 
//NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentsDirectory = [self getImagePath];
NSLog(@"Image Path : %@",documentsDirectory);
NSError *error1;
NSString *filepath1;
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:&error1];
if (files == nil) 
    NSLog(@"Error reading contents of documents directory: %@", [error1 localizedDescription]);

NSLog(@"FileName: %@",imageName);
BOOL success = NO;
for (NSString *file in files)

    NSLog(@"file in Files is %@",file);
    if([file isEqualToString:[NSString stringWithFormat:@"%@",imageName]])
    
        filepath1 = [documentsDirectory stringByAppendingPathComponent:file];
        NSLog(@"Full Path :%@",filepath1);
        success = YES;
    





    if(success == YES)
    
        cell.imageView.image = [UIImage imageWithContentsOfFile:filepath1];
    
    else if(success != YES)
    
        cell.imageView.image = [UIImage imageNamed:@"newfund.png"];
    


    UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(60.0, 0, 120.0, 
                                                                tableView.rowHeight)] autorelease]; 
    [cell addColumn:50];
    label.textColor = [UIColor blackColor];
    label.tag = LABEL_TAG; 
    label.font = [UIFont systemFontOfSize:12.0]; 
    //NSLog(@"%@",[[array1 objectAtIndex:indexPath.row] valueForKey:@"FundName"]);
    label.text = [NSString stringWithFormat:@"%@",[[array1 objectAtIndex:indexPath.row] valueForKey:@"FundName"]];
    //NSLog(@"FundName: %@",label.text);
    label.textAlignment = UITextAlignmentCenter; 
    //label.textColor = [UIColor blueColor]; 
    label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | 
    UIViewAutoresizingFlexibleHeight; 
    [cell.contentView addSubview:label];        

return cell;

【问题讨论】:

你应该为 -tablView:cellForRowAtIndexPath 方法编写你的代码,这样我们就可以提供如何改进它的提示。 @Parth,做一个快速回顾,我会在你找到你要找的文件后添加一个 break 语句。另外,您为什么要创建一个全新的字符串进行比较?你应该做if([file isEqualToString:imageName]) @PARTH,这些 png 文件有多大? @Black Frog:png 文件大小为 4 KB。 @Black Frog:我试着按照你说的改变一切,但仍然没有提高性能。现在我想将图像加载为 Lazy Table Images,但图像位于我的应用程序的 Document 目录中。那么有没有一种方法可以使用 Lazy table 图像呢? 【参考方案1】:

您可以从文档目录添加图像,然后将它们作为惰性表格图像添加到表格视图中。

为此,您可以使用以下内容

查看下面的 SDWebImage 存储库链接。

https://github.com/rs/SDWebImage#readme

这会对你有所帮助。

现在你需要做一个小改动:

[cell.imageView setImageWithURL:[NSURL fileURLWithPath:test1.png]
           placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

代替

[cell.imageView setImageWithURL:[NSURL URLWithString:test1.png]
           placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

乐于助人:-)

【讨论】:

【参考方案2】:

当您在tableView:cellForRowAtIndexPath: 中配置单元格时,您应该检查是否已加载图像(如果已加载 - 从那里显示)。

当图像被加载(全部或部分)时,您应该调用表格视图的reloadData / reloadRowsAtIndexPaths:withRowAnimation: / reloadSections:withRowAnimation:) 从缓存中删除旧生成的表格单元格。

更新:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

        UIImageView *imgView = [[[UIImageView alloc] init] autorelease];
        imgView.hidden = YES;
        imgView.tag = 5555;
        [cell addSubview:imgView];
    

    if (nil != _images[indexPath.row]) 
        UIImageView *imgView = (UIImageView *)[cell viewWithTag:5555];
        imgView.image = _images[indexPath.row];
        [imgView sizeToFit];
        imgView.hidden = NO;
    

    return cell;

这里的 _images[] 是带有单元格图像的容器(UIImage 指针)。我想我们只有一个部分让我自己在这个例子中使用一些简单的容器。如果未加载图像,则 _images[] 存储 nil,否则 - 必要的 UIImage*。

在加载图像时调用的某些方法中,您应该执行以下步骤:

    为对应的_images[]索引保存图片。

    调用 tableView 的 reloadRowsAtIndexPaths:withRowAnimation: 以获取必要的部分和行(当然来自主线程)。

【讨论】:

+1 快速回复并感谢您的帮助。我不太清楚您所说的。能详细解释一下吗? 嘿kpower,你能举个例子吗?或链接到一些讨论这件事的文章?【参考方案3】:

一种方法可能是,当您加载一个单元格时,您可以启动一个新线程来加载图像。

[NSThread detachNewThreadSelector:@selector(loadData:) toTarget:self withObject:nil];

然后在同一个类中你需要方法来做工作和回调。

-(void) loadData:(id)object

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    //do stuff here
    [pool release];
    //Call back
    [self performSelectorOnMainThread:@selector(loadDataComplete:) withObject:nil waitUntilDone:NO];



-(void) loadDataComplete:(id)object

    // Maybe be more clever and pass the indexPath around so you can just load that row.
    [tableView reloadData]; 

【讨论】:

【参考方案4】:

当单元格第一次可见时,调用tablView:cellForRowAtIndexPath: 方法来显示文本。将单元格标记为可见。使用异步线程(子类 NSOperation)加载图像。当图像准备好用于特定单元格时,将–reloadRowsAtIndexPaths:withRowAnimation: 发送到表视图以从并发线程加载该特定行。我不会使用reloadData,因为这会导致表中的所有数据都被重新加载,并且可能会影响滚动性能。

【讨论】:

【参考方案5】:

查看LazyTableImages sample code by Apple

此示例演示了一种多阶段加载和 显示一个 UITableView。它首先从加载相关文本 一个 RSS 提要,以便表格可以尽快加载,然后 异步下载每一行的图像,因此 UI 更丰富 反应灵敏。

【讨论】:

以上是关于延迟后如何在 tableView 中加载图像?的主要内容,如果未能解决你的问题,请参考以下文章

在tableview中加载异步图像,它们在每次滚动时消失

如何使tableView中单元格中的图像一致显示?

填充单元格后如何在单元格中加载/显示 UIImageView

如何在后台工作人员运行时在 uwp 中加载图像

如何在 Ionic 2 或 3 应用程序中加载实际图像之前显示占位符图像

如果在 JSON 对象中加载空图像 URL,则应用程序崩溃