【问题标题】:Setting image in custom uitableviewcell causes lag在自定义 uitableviewcell 中设置图像会导致延迟
【发布时间】:2014-06-29 03:20:34
【问题描述】:

我有一个使用自定义单元格的 uitableview。但是,当我滚动表格视图时,会有一些严重的滞后。当我用图像设置 UIImaveView 的图像属性时会发生这种情况。我正在从目录访问图像。但由于文件 IO 很慢,我使用 dispatch_async 将图像加载到单独线程上的 UIImage 对象中。

但仍有一些滞后。当我在没有任何图像的情况下上下滚动行时,滚动非常流畅。但是,当该行实际上有图像时,就会出现滞后。动量滚动将停止,然后应用程序变得无响应,然后当图像最终加载时,动量会从中断处继续。

我不确定是什么导致了延迟。起初我认为这与图像太大有关,所以我尝试将其缩小。仍然滞后。同样,如果我不在自定义单元格中设置图像,则没有延迟。但是当我设置它时会有滞后。我不知道如何解决这个问题。

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    DHTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kReuseIdentifierGoalCell forIndexPath:indexPath];
    [self configureCell:cell forIndexPath:indexPath isForOffscreenUse:NO];

    return cell;
 }


- (void)configureCell:(DHTableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath isForOffscreenUse:(BOOL)offscreenUse {
    if (cell == nil) {
        return;
    }

    [cell setDelegate:self];

    PATH_TO_FILE = SQLITE_QUERY_TO_GET_PATH; //some pseudo codes

    __weak typeof(sSelf)wSelf = sSelf;
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         __strong typeof(wSelf)sSelf = wSelf;
         UIImage *unscaled_image = [UIImage imageWithContentsOfFile:PATH_TO_FILE];
         UIImage *image = [unscaled_image imageScaledToFitInSize:kCellUIImageSize];
         __weak typeof(sSelf)wSelf = sSelf;
         dispatch_async(dispatch_get_main_queue(), ^{
             __strong typeof(wSelf)sSelf = wSelf;
             DHTableViewCell *cell = (id)[sSelf.tableView cellForRowAtIndexPath:indexPath];
             if (cell) {
                 [cell.imageStored setImage:image]; //Commenting this out relieves all lag
             }
         });
     });
 }

【问题讨论】:

  • 你从哪里调用这个代码片段?每个单元格是否有不同的图像?
  • 在tableview中调用:cellforindexpath:
  • 每个单元格都有不同的图像。
  • 我不知道这种方法。你能发布整个方法。它与cellForRowAtIndexpath 有什么关系?我注意到你在这段代码中回调cellForRowAtIndexPath,这看起来很奇怪。通常你会在cellForRowAtIndexPath 调用的后台线程中加载图像 - 然后你已经有了对单元格的引用
  • 好的,我更新了代码以使其更易于理解。我使用cellForRowAtIndexPath 来获取对单元格的引用的原因是,当图像最终加载时,单元格有可能最终离开屏幕。表格视图的工作方式是回收单元格,因此如果我只使用方法中单元格的引用,它可能最终会更新错误的单元格。 (如果我误解了这是如何工作的,请纠正我)

标签: ios uitableview uiimageview uiimage


【解决方案1】:

@Calimari328 我讨厌将其作为答案,因为它并不能真正回答您的问题,但事实是您真正应该做的是使用库来实现这一目标。例如SDWebImage

例子:

#import <SDWebImage/UIImageView+WebCache.h>

...

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:MyIdentifier] autorelease];
    }

    // Here we use the new provided setImageWithURL: method to load the web image
    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    cell.textLabel.text = @"My Text";
    return cell;
}

您必须重新考虑这一点,单元格会被重复使用,这意味着每次滚动应用时都会尝试再次下载图像。性能如何?记忆 ?缓存?加工?

当您仔细考虑它时,它比简单的异步任务要复杂得多。幸运的是,有一些开源项目可以实现这一目标。无需重新发明轮子。

请注意,如果您想编写自己的代码,我并不是在宣传任何库,您也可以这样做。也可以search on the web 方便实现。

【讨论】:

  • 这是一个很棒的开源库,但我的项目没有从 Internet 加载它。它正在从磁盘加载它。
  • 再一次,我只能建议您在阅读了An asynchronous memory + disk image caching with automatic cache expiration handling的描述后尝试一下
猜你喜欢
  • 1970-01-01
  • 2010-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-27
  • 2012-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多