ios - UITableView 滚动不流畅

标签 ios uitableview uiimage xamarin smooth-scrolling

我的 UITableView 和包含 UIImageView 的 UITableViewCell 出现平滑滚动问题。在整个 StrackOverflow 中都可以找到类似的问题,但没有一个建议的解决方案可以帮助我完全摆脱滞后。

我的情况很常见:

  1. 图像存储在应用程序存储中(在我的应用程序包示例中)
  2. 图片可以有不同的尺寸(500x500、1000x1000、1500x1500)
  3. 我需要在 UITableView 中显示这些图像,其中 UIImageView 大小为 120x120(视网膜)

我遵循了多个优化技巧并设法优化了很多滚动。 不幸的是,它仍然不完美。这是我的场景:

  1. 首先我将所有图像加载/处理/调整大小逻辑移至后台线程
  2. 启用 UITableViewCell 重用
  3. 一旦 UITableViewCell 在 View 中,我就清除旧值(设置为 null)并启动后台线程以加载图像
  4. 此时我们处于后台线程中,我添加了 500 毫秒的延迟以避免经常设置新图像(以防我们快速滚动)(参见下面的解释)
  5. 如果 UIImage 存在于静态图像缓存中(带有 UIImage 实例的常规字典)- 获取那个并转到第 9 步。
  6. 如果不是 - 使用 url 从 bundle (imageWithName) 加载新图像到 app bundle(在现实世界场景中,图像将存储到应用程序存储,而不是 bundle)
  7. 加载图像后,使用图形上下文将其调整为 120x120
  8. 将调整后的图片保存到静态图片缓存
  9. 此时我们有 UIImage 的实例并且进程在后台线程中。从这里我们返回到具有给定图像的 UI 线程
  10. 如果数据上下文被清除(例如 UITableViewCell 消失或被重新用于显示另一张图像),我们将跳过对当前可用图像的处理。
  11. 如果数据上下文相同 - 使用 alpha 动画 (UIView.Animate) 将 UIImage 分配给 UIImageView
  12. 一旦 UITableViewCell 超出 View - 清除数据上下文

最初,在启动新的后台线程以在此处获取图像之前(第 1 步)是在没有后台线程的情况下检查 UIImage 缓存。在这种情况下,如果我们在缓存中有图像,我们会立即分配它,这会在快速滚动期间引入很大的延迟(只要我们立即获取图像,我们就会经常分配图像)。这些行在我下面所附的示例中进行了评论。

还有两个问题:

  1. 在滚动过程中的某个时刻,我仍然有一个小的滞后(在 当我将新的 UIImage 分配给 UIImageView 时。
  2. (这个更明显)当您点击项目并从详细信息返回时,在返回导航动画完成之前会有一个滞后。

任何有关如何处理这两个问题或如何优化我的场景的建议都将受到赞赏

请考虑用 Xamarin 编写的示例,但我不认为 Xamarin 是问题的原因,只要我对用 ObjectiveC 编写的应用也有同样的问题。

Smooth Scrolling Test App

最佳答案

您是否每次都尝试使用保存在 Bundle 中的一张 120x120 图像填充您的 TableView?这样你就可以检查你的 Image rendering

是否出现问题

与其将所有图像调整为 120x120 并将它们保存在缓存中,我建议创建并使用所有图像的缩略图。您已经以某种方式这样做了,但是您已经这样做了几次(每次滚动或缓存已满时)。

在我们的上一个项目中,我们有一个带有书籍封面的 UICollectionView。大多数封面都在 400-800kb 之间,滚动时的感觉非常糟糕。所以我们为每个图像创建了一个缩略图(缩略图大约 40-50kb)并使用缩略图而不是真正的封面。奇迹般有效!我附加了缩略图创建功能

- (BOOL) createThumbnailForImageAtFilePath:(NSString *)sourcePath withName:(NSString *)name {

    UIImage* sourceImage = [UIImage imageWithContentsOfFile:sourcePath];
    if (!sourceImage) {
        //...
        return NO;
    }

    CGSize thumbnailSize = CGSizeMake(128,198);

    float imgAspectRatio = sourceImage.size.height / sourceImage.size.width;
    float thumbnailAspectRatio = thumbnailSize.height/thumbnailSize.width;

    CGSize scaledSize = thumbnailSize;

    if(imgAspectRatio >= thumbnailAspectRatio){
         //image is higher than thumbnail
         scaledSize.width = scaledSize.height * thumbnailSize.width / thumbnailSize.height;
    }
    else{
        //image is broader than thumbnail
        scaledSize.height = scaledSize.width * imgAspectRatio;
    }

    UIGraphicsBeginImageContextWithOptions( scaledSize, NO, 0.0 );
    CGRect scaledImageRect = CGRectMake( 0.0, 0.0, scaledSize.width, scaledSize.height );
    [sourceImage drawInRect:scaledImageRect];
    UIImage* destImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    NSString* thumbnailFilePath = [[self SOMEDIRECTORY] stringByAppendingPathComponent:name];

   BOOL success = [UIImageJPEGRepresentation(destImage, 0.9) writeToFile:thumbnailFilePath atomically:NO];

return success;

关于ios - UITableView 滚动不流畅,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26310754/

相关文章:

ios - Swift 中的网络层,完成 block 和错误

ios - selectRowAtIndexPath 在 vi​​ewWillAppear 中失败

ios - 如何在 UITableView 中显示/隐藏 UISearchController searchBar?

ios - 如何在 iOS 中滚动 UITableView

objective-c - 将图像发送到另一个 View Controller UIImageView IOS 5.1

iOS 13 `withTintColor` 不服从我分配的颜色

ios - 有没有办法在片段着色器中使用64个以上的向量?或替代?

ios - <NSMutableURLRequest : 0x1c0c7ae0> { URL: (null) } in Objective C

ios - iOS 7 上的 UIVibrancyEffect

iOS11 滚动偏移 - 过渡问题