设置 UIImageView 的图像属性会导致严重滞后

2024-01-09

让我告诉你我遇到的问题以及我如何尝试解决它。我有一个 UIScrollView ,它在从左到右滚动时加载子视图。每个子视图有 10-20 个图像,每个图像大约 400x200。当我从一个视图滚动到另一个视图时,我遇到了相当大的延迟。

经过调查,我发现卸载所有视图并再次尝试后,延迟消失了。我认为图像的同步缓存是造成延迟的原因。所以我创建了一个 UIImageView 的子类,它异步加载图像。加载代码如下所示(self.dispatchQueue返回一个串行调度队列)。

- (void)loadImageNamed:(NSString *)name {
    dispatch_async(self.dispatchQueue, ^{
        UIImage *image = [UIImage imageNamed:name];

        dispatch_sync(dispatch_get_main_queue(), ^{
            self.image = image;
        });
    });
}

然而,在将我的所有 UIImageViews 更改为这个子类之后,我仍然遇到延迟(我不确定它是否减少了)。我把问题的原因归结为self.image = image;。为什么这会导致如此大的延迟(但仅在第一次加载时)?

请帮我。 =(


编辑 3:iOS 15 现在提供UIImage.prepareForDisplay(completionHandler:) https://developer.apple.com/documentation/uikit/uiimage/3750844-preparefordisplay.

image.prepareForDisplay { decodedImage in
    imageView.image = decodedImage
}

or

imageView.image = await image.byPreparingForDisplay()

编辑 2:这是一个包含一些改进的 Swift 版本。 (未经测试。)https://gist.github.com/fumoboy007/d869e66ad0466a9c246d https://gist.github.com/fumoboy007/d869e66ad0466a9c246d


编辑:实际上,我相信所有必要的就是以下内容。 (未经测试。)

- (void)loadImageNamed:(NSString *)name {
    dispatch_async(self.dispatchQueue, ^{
        // Determine path to image depending on scale of device's screen,
        // fallback to 1x if 2x is not available
        NSString *pathTo1xImage = [[NSBundle mainBundle] pathForResource:name ofType:@"png"];
        NSString *pathTo2xImage = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"png"];

        NSString *pathToImage = ([UIScreen mainScreen].scale == 1 || !pathTo2xImage) ? pathTo1xImage : pathTo2xImage;


        UIImage *image = [[UIImage alloc] initWithContentsOfFile:pathToImage];

        // Decompress image
        if (image) {
            UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);

            [image drawAtPoint:CGPointZero];

            image = UIGraphicsGetImageFromCurrentImageContext();

            UIGraphicsEndImageContext();
        }


        // Configure the UI with pre-decompressed UIImage
        dispatch_async(dispatch_get_main_queue(), ^{
            self.image = image;
        });
    });
}

原始答案:事实证明并非如此self.image = image;直接地。 UIImage图像加载方法不会立即解压缩和处理图像数据;他们在视图刷新其显示时执行此操作。所以解决方案是降低到 Core Graphics 级别,自己解压和处理图像数据。新代码如下所示。

- (void)loadImageNamed:(NSString *)name {
    dispatch_async(self.dispatchQueue, ^{
        // Determine path to image depending on scale of device's screen,
        // fallback to 1x if 2x is not available
        NSString *pathTo1xImage = [[NSBundle mainBundle] pathForResource:name ofType:@"png"];
        NSString *pathTo2xImage = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"png"];
        
        NSString *pathToImage = ([UIScreen mainScreen].scale == 1 || !pathTo2xImage) ? pathTo1xImage : pathTo2xImage;
        
        
        UIImage *uiImage = nil;
        
        if (pathToImage) {
            // Load the image
            CGDataProviderRef imageDataProvider = CGDataProviderCreateWithFilename([pathToImage fileSystemRepresentation]);
            CGImageRef image = CGImageCreateWithPNGDataProvider(imageDataProvider, NULL, NO, kCGRenderingIntentDefault);
            
            
            // Create a bitmap context from the image's specifications
            // (Note: We need to specify kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little
            // because PNGs are optimized by Xcode this way.)
            CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
            CGContextRef bitmapContext = CGBitmapContextCreate(NULL, CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerComponent(image), CGImageGetWidth(image) * 4, colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
            
            
            // Draw the image into the bitmap context
            CGContextDrawImage(bitmapContext, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
            
            //  Extract the decompressed image
            CGImageRef decompressedImage = CGBitmapContextCreateImage(bitmapContext);
            
            
            // Create a UIImage
            uiImage = [[UIImage alloc] initWithCGImage:decompressedImage];
            
            
            // Release everything
            CGImageRelease(decompressedImage);
            CGContextRelease(bitmapContext);
            CGColorSpaceRelease(colorSpace);
            CGImageRelease(image);
            CGDataProviderRelease(imageDataProvider);
        }
        
        
        // Configure the UI with pre-decompressed UIImage
        dispatch_async(dispatch_get_main_queue(), ^{
            self.image = uiImage;
        });
    });
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设置 UIImageView 的图像属性会导致严重滞后 的相关文章

  • 方法与管道

    在 Angular 应用程序中的模板插值中使用管道和方法有区别吗 例如 h1 name toLowerCase h1 vs h1 name lowercase h1 就性能而言 是有真正的收获还是只是个人喜好 我知道调用模板中的方法通常会降
  • mysql查询先慢后快

    我有 2 个 myISAM 表 分别称为 tests 和 completed tests 一个有 170 个条目 另一个有 118k 条目 当我运行此查询时 SELECT ct archive ct status ct score ct u
  • JavaScript fetch API - 为什么response.json()返回一个promise对象(而不是JSON)? [复制]

    这个问题在这里已经有答案了 我刚刚开始学习 Fetch API https developer mozilla org en US docs Web API Fetch API Using Fetch https developer moz
  • 为什么我应该使用 std::async?

    我试图深入探索新 C 11 标准的所有选项 在使用 std async 并阅读其定义时 我注意到两件事 至少在使用 gcc 4 8 1 的 linux 下 它被称为async 但它有一个真正的 顺序行为 基本上在你调用的行中future与您
  • Itertools 与嵌套循环性能

    我必须生成列表中所有两对项目组合 现在 我知道有两种方法可以实现这一点 嵌套 for 循环和 python 的内置迭代工具 from itertools import combinations foo 1 2 3 4 for i in xr
  • 如何让node.js中的线程休眠而不影响其他线程?

    As per 了解 Node js 事件循环 http blog mixu net 2011 02 01 understanding the node js event loop node js支持单线程模型 这意味着如果我向 Node j
  • JS中函数声明速度差异

    我运行了一个简单的 jsperf 测试 在 Firefox 中运行时一切都按预期进行 但当我在 Google Chrome 中运行测试时却感到困惑 该测试正在测试在 JavaScript 中声明函数然后调用它们的不同方式 我的猜测是 Chr
  • 异步编程设计模式

    我正在为 CF NET 开发一个小型技术框架 我的问题是 我应该如何编写异步部分的代码 在 MSDN 上阅读了很多内容 但我不太清楚 所以 这是代码 public class A public IAsyncResult BeginExecu
  • 如何在大空间尺度上加速A*算法?

    From http ccl northwestern edu netlogo models community Astardemo http ccl northwestern edu netlogo models community Ast
  • 公共领域还好吗?

    在你像我最初那样做出直觉反应之前 请阅读整个问题 我知道它们让你感觉很脏 我知道我们以前都被烧伤过 我知道这不是 好风格 但是公共场所可以吗 我正在开发一个相当大规模的工程应用程序 该应用程序创建并使用结构的内存模型 从高层建筑到桥梁再到棚
  • 如何优化 R 中的 sapply 来计算数据帧上的运行总计

    我在 R 中编写了一个函数来按月份计算累积总数 但随着数据集变大 我的方法的执行时间呈指数增长 我是一名 R 程序员新手 你能帮我提高效率吗 该函数以及我调用该函数的方式 accumulate lt function recordnum d
  • 移动物体而不实际接触物体

    我是 iPhone 开发的初学者 我一直在寻找这个问题的答案 但还没有找到任何东西 我想做的是允许用户移动对象而无需实际触摸该对象 他们可以触摸屏幕上的任何位置 并且当他们移动时 对象将从原来的位置向用户的方向移动移动但不会跳到他们的触摸位
  • 如何检测 UIImage 的非透明部分何时与 UIImage 的另一个非透明部分接触

    我在完成一些我认为会容易得多的事情时遇到了困难 每当 UIImage 中图片的非透明部分接触 UIImage 中包含的图像的另一个非透明部分时 我试图运行一个方法 我举了一个例子来帮助进一步解释我的问题 正如您在上图中看到的 我有两个三角形
  • CSS3 - 性能最佳实践是什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Yii框架异步请求

    我有一个执行 3 个任务的 ajax 请求 保存模型 数据库 发电子邮件 给出成功或失败的消息 因为这个任务需要的时间太长了 用户最多可以等待 20 秒以获得响应 成功或失败消息 如果用户关闭浏览器 则其会停止用户当前进程的操作之一 这是糟
  • 如何使用 Java2D 创建硬件加速图像?

    我正在尝试创建一个快速图像生成器 它可以执行大量 2d 转换和形状渲染 因此我尝试使用 BufferedImage 然后获取 Graphics2D 对象来执行所有绘图 我现在主要关心的是 make 速度非常快 所以我创建一个像这样的 Buf
  • Node.js:您什么时候知道异步任务集合何时完成?

    我想深入一个目录 并根据正则表达式检查我在其中看到的每个文件的名称 基本上是通用unix的一个版本find命令 仅用 Node js 编写 我不关心文件的顺序 但我确实想确保获得所有文件 我有以下代码 我认为 它接近我想要的 它需要一个 s
  • 进行异步调用时,“yield”在龙卷风中如何工作?

    最近我在学习龙卷风简介 我遇到了以下代码 class IndexHandler tornado web RequestHandler tornado web asynchronous tornado gen engine def get s
  • 为什么在 this 方法中添加 If 语句会大大降低速度?

    我在中遇到过这个回答另一个问题 https stackoverflow com questions 12233594 faster way to apply alpha to a jpeg in an android app 我试图诊断哪些
  • 与简单的文件请求相比,您预计 Web 服务请求的响应时间开销是多少?

    我正在开发一个 asp net Web 服务应用程序 以向使用 jQuery ajax 发出请求的小部件提供 json 格式的数据 我一直在使用 FireBug Net 视图来检查数据请求需要多长时间 在我最初的原型中 我只是请求静态 js

随机推荐

  • Scala 解释器有哪些限制和解决方法?

    什么样的结构需要 scalac 编译以及如何制作可在解释器中工作的等效结构 Edit 我想使用 scala 而不是 python 作为脚本语言 使用 usr bin scala 您应该能够在 REPL 中执行任何可以在外部代码中执行的操作
  • 将 UIImage 转换为 NSString(反之亦然)

    我需要一种方法来转换 NSString 中的 UIImage 然后将 NSString 转换回 UIImage Thanks 适用于 gt iOS 7 NSString imageToNSString UIImage image NSDat
  • mupdf for android:ndk-build问题(错误:typedef的重新定义......)

    我正在按照必要的步骤安装适用于 Android 的 MuPDF MuPDF 是在我的系统上构建的 我能够使用 C 来利用它 现在尝试使用 Android README 中的所有步骤均已成功执行 但当我执行到步骤 10 时 我就必须这样做nd
  • Rails 错误:`rescue in ':未初始化的常量 Bundler (NameError)

    今天早些时候 我更新了系统上的 gems gem update 它更新了一些 gem 但之后我无法启动我的 Rails 服务器 我收到此错误 Users gugguson rubys my rails app config boot rb
  • NoSuchMethodError Lcom/google/gson/Gson;改造响应后

    因此 我的应用程序发布近一年了 但没有看到此问题 现在它出现了 即使现在 我手机上的调试版本也没有这个问题 我从 Android Studio 打开的任何模拟器都没有任何问题 然而 Google 开发者控制台中的预发布报告中的几乎每个模拟器
  • 了解编译器的工作原理

    我正在学习 C 编程语言 我对编译器如何创建可执行文件有疑问 我的书上说 C 是一种编译语言 因此您需要将源代码翻译为计算机可以执行的文件 这个文件是由编译器生成的 称为目标代码 obj 但是像 hello world 程序这样的程序是由我
  • ostream 链接,输出顺序

    我有一个函数需要ostream引用作为参数 将一些数据写入流 然后返回对同一流的引用 如下所示 include
  • 如何让 Turtle 等待按下的键

    我和我的团队创建了一款在 Turtle 上运行的棋盘游戏 我们很难在不需要 IDE 控制台的情况下运行游戏 我们希望使用 onkeypress 来运行我们的游戏 这样用户就不必离开游戏窗口 import turtle from turtle
  • 普罗米修斯上的多个目标

    我已经在Centos上配置了prometheus 版本详细信息如下 prometheus 2 5 0 linux 386 我在 prometheus yml 配置文件中添加了两个目标 所有服务器节点导出器都在运行 配置如下 scrape c
  • PL SQL For 循环 Sys_RefCursor

    我正在使用 Oracle 12c 在 PL SQL 中我可以做到这一点 set serveroutput on declare begin for x in select 1 as y from dual loop dbms output
  • ttk 应用样式时打开辅助窗口

    这是我的代码 from Tkinter import import ttk tkMessageBox import os font Avenir 24 b ttk Style b configure TButton font font cl
  • 如何更改 Textview 中的字母间距?

    如何更改文本视图中的字母间距 如果我里面有 HTML 文本会有帮助吗 我不能在我的代码中使用 webview 附 我在带有 HTML 文本的文本视图中使用自己的字体 从 API 21 开始 有一个选项设置字母间距 可以调用方法设置字母间距
  • 如何在我的 Angular2 应用程序中列出/输出 @Routes 中的所有路由

    我有一个快速的问题 我目前正在浏览https angular io docs ts latest api router Router class html https angular io docs ts latest api router
  • 如何用pl/sql循环接受用户输入?

    我希望能够根据用户输入将可变数量的行插入表中 例如 Please enter value enter done when no more values value 1 Please enter value enter done when n
  • 在 iFrame 中嵌入 Google Apps 脚本

    我正在尝试将使用 Google Apps 脚本中的 Javascript 动态构建的页面嵌入到我的 iFrame 网站中 但未显示 iFrame 的内容 Google Apps 脚本具有同源策略 可阻止其加载 我想做的是 我删除了完整链接
  • 类的对象..无法转换为字符串

    我做了我的第一堂课 但在将对象转换回字符串时遇到了麻烦 class Cryption var data var salt function construct data salt this gt data data this gt salt
  • 在 Windows 中从 cmd 运行 R

    我正在尝试安装 rtools 以便我可以安装另一个软件包 Google 的 causalimpact 并且该过程表明我的 R 路径环境存在问题 主要问题 我跑不了R从命令窗口 预期的行为是输出如下并给出 gt prompt R versio
  • 如何设置AMP图像居中对齐

    如何在 amp 页面中进行如下设置 p align center img src img LOCK1 png width 40 img src img lock2 png width 40 img src img LOCK3 png wid
  • 无法加载文件或程序集“PDFNet”或其依赖项之一。尝试加载格式不正确的程序

    我正在尝试从 VS2012 中的空白 Web 表单模板构建示例 Web 应用程序 并向其中添加 PDFNet dll 如果我在 NET 3 5 中运行该项目没有问题 如果我在 NET gt 4 中运行它 我会收到此错误 无法加载文件或程序集
  • 设置 UIImageView 的图像属性会导致严重滞后

    让我告诉你我遇到的问题以及我如何尝试解决它 我有一个 UIScrollView 它在从左到右滚动时加载子视图 每个子视图有 10 20 个图像 每个图像大约 400x200 当我从一个视图滚动到另一个视图时 我遇到了相当大的延迟 经过调查