后台生成二维码后,主线程设置UIImage到UIImageView耗时0.7秒求助
问题排查与解决:主线程设置二维码图片耗时过长
这个场景我之前处理过好几次,核心问题出在CIImage转UIImage的时机和方式上,咱们来一步步拆解原因和解决办法:
为什么设置image会耗时0.7秒?
- 延迟渲染的坑:你当前用
UIImage(ciImage:)创建的图片并没有提前完成位图化,它本质上只是对CIImage的一个引用。当你在主线程把它赋值给UIImageView时,系统才会在主线程实时进行CIImage的解码、渲染和位图转换,这部分操作非常耗时——尤其是你把二维码缩放了10倍,尺寸不小,开销自然被放大了。 - 后台任务没做彻底:后台线程只完成了CIImage的生成和缩放,但把最耗时的位图转换工作丢给了主线程,直接导致主线程卡顿。
解决方法:把位图转换移到后台线程
我们只需要在后台生成二维码的同时,完成CIImage到位图UIImage的转换,让主线程拿到直接可用的位图图片,这样设置image的操作就几乎没有开销了。
修改后的二维码生成函数
// 提前创建共享的CIContext,避免重复初始化开销(放在类属性或全局都可以) let sharedCIContext = CIContext(options: [ .cacheIntermediates: true, .useSoftwareRenderer: false // 优先用GPU加速,性能更好;如果遇到兼容问题可以改成true ]) func generateQRCode(from string: String, completion: @escaping (UIImage) -> ()) { DispatchQueue.global(qos: .background).async { let data = string.data(using: .ascii) guard let filter = CIFilter(name: "CIQRCodeGenerator") else { completion(UIImage(named: "default")!) return } filter.setValue(data, forKey: "inputMessage") guard let qrImage = filter.outputImage else { completion(UIImage(named: "default")!) return } let transform = CGAffineTransform(scaleX: 10, y: 10) let scaledImage = qrImage.transformed(by: transform) // 关键:在后台完成CIImage到CGImage的转换(位图化) guard let cgImage = sharedCIContext.createCGImage(scaledImage, from: scaledImage.extent) else { completion(UIImage(named: "default")!) return } // 用CGImage创建UIImage,这是直接的位图图片 let finalImage = UIImage(cgImage: cgImage) completion(finalImage) } }
额外优化建议
- 确保UIImageView的尺寸和生成的二维码图片尺寸一致,避免主线程额外做缩放渲染。
- 如果你的App需要频繁生成二维码,复用CIContext和CIFilter可以进一步降低开销。
修改后再测试主线程设置image的耗时,应该会降到几毫秒级别,彻底解决卡顿问题。
内容的提问来源于stack exchange,提问作者Mahdiyar
相关产品推荐
相关产品推荐

