我在UITableView上有包含UIImageView的UITableViewCell时出现了平滑滚动的问题。在StrackOverflow各处都可以找到类似的问题,但是所提出的解决方案都无法帮助我完全摆脱这一滞后。

我的情况很普遍:

  • 图像存储在应用程序存储中(在我的应用程序 bundle 包示例中)
  • 图片可以具有不同的大小(500x500、1000x1000、1500x1500)
  • 我需要在UITableView中显示UIImageView大小为120x120(视网膜)的那些图像

  • 我遵循了多个优化技巧,并设法对滚动进行了很多优化。
    不幸的是,它仍然不是完美的。这是我的情况:
  • 首先,我将所有图像加载/处理/调整大小逻辑移至后台线程
  • 启用UITableViewCell重用
  • UItViewCell出现在 View 中时,我会清除
  • (清除设置为null的旧值)并启动后台线程以加载图像
  • 此时,我们处于后台线程中,我添加了500 ms的延迟,以避免经常设置新图像(以防我们快速滚动)(请参见以下说明)
  • (如果UIImage存在于静态图像缓存中(带有UIImage实例的常规词典))-获取该图像并转到步骤9。
  • 如果不是-使用URL从 bundle 包(imageWithName)加载新图像到应用程序 bundle 包(在现实情况下,图像将存储到应用程序存储中,而不是 bundle 包中)
  • 加载图像后
  • 使用图形上下文
  • 将其大小调整为120x120
  • 将调整大小的图像保存到静态图像缓存
  • 此时,我们有UIImage实例,并且进程在后台线程中。从这里,我们使用给定的图像
  • 返回UI线程
  • 如果清除了数据上下文(例如UITableViewCell消失或被重用于显示其他图像),则跳过对当前可用图像的处理。
  • 如果数据上下文相同-使用alpha动画(UIView.Animate)将UIImage分配给UIImageView
  • UITableViewCell不在 View 范围内时
  • -清除数据上下文

  • 最初,在开始新的后台线程以在此处获取图像之前(步骤1)是在没有后台线程的情况下进行UIImage缓存检查。在这种情况下,如果我们将图像保存在缓存中,则会立即对其进行分配,这在快速滚动期间会带来很大的延迟(我们将图像分配给通常只要我们立即获取它们就可以)。这些行在下面附上的示例中进行了注释。

    仍然有两个问题:
  • 在滚动过程中的某个时候,我仍然有一个小滞后(在
    我将新的UIImage分配给UIImageView的时刻。
  • (这一点更引人注目),当您单击项目并从详细信息返回时,在向后导航动画完成之前有一个滞后。

  • 关于如何处理这两个问题或如何优化我的方案的任何建议,均表示赞赏。

    请考虑使用Xamarin编写的示例,但是只要我也对用ObjectiveC编写的应用程序存在相同的问题,我不认为Xamarin是问题的原因。

    Smooth Scrolling Test App

    最佳答案

    你们是否都尝试过只用一张保存在TableView中的120x120图像填充Bundle?这样,您可以检查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/

    10-16 05:45