
ios加载大量高分辨率图片是部分图片显示空白并且报错(CGBitmapContextInfoCreate: unable to allocate 530841600 bytes for bitmap data)
作者: boyyang
分类: Swift
发布: 2025-06-18 08:37:35
更新: 2025-06-18 08:37:35
浏览: 6
背景
在开发ios应用的时候,我有个图片无限加载的场景。由于有很多图片都是高分辨率的图片。在开发阶段这些图片都能够正常加载。但是打包到真机测试的时候,有些图片就无法显示并且在xcode控制台中显示(CGBitmapContextInfoCreate: unable to allocate 530841600 bytes for bitmap data)在网上找了很多相关的解决方案。大多数都是说使用kingfisher,SDImage等等用来做图片缓存。但是使用后也会出现这个问题。而且这个问题还是偶发性的。并不是每次都出现,但是在图片加载越来越多的时候就会出现该问题。
问题分析
根据报错信息感觉就是因为图片太大了导致无法渲染,但是如果单独渲染这张图片,它又能正常显示。由于图片已经进行过压缩了,所以也就无法在图片压缩上做处理了。
解决方案
我通过使用Nuke图片缓存框架获取到图片数据后为图片生成缩略图,然后再渲染到页面,本来是根据页面图片的宽高来设置byPreparingThumbnail的ofSize的,但是渲染出来的图片清晰度有点低,所以参数都乘上2后图片也就清晰了。打包后再次测试也就没有显示空白,也没有报错了
部分代码如下:
import SwiftUI
import Nuke
struct SDWebImage: View {
@State var url: URL
@State var thumbnailUrl: URL?
@State var size: CGSize = .init(width: 200, height: 200)
@State private var image: UIImage?
func getImage() async throws {
let imageTask = ImagePipeline.shared.imageTask(with: url)
for await _ in imageTask.progress {
}
let image = try await imageTask.image.byPreparingThumbnail(ofSize: CGSize(width: size.width * 2, height: size.height * 2))
self.image = image
}
var body: some View {
if (image != nil) {
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: size.width, height: size.height)
.clipShape(
RoundedRectangle(
cornerSize: CGSize(width: 10, height: 10),
style: .continuous
)
)
}else{
Group {
if #available(iOS 26.0, *) {
Color
.clear
.frame(width: size.width, height: size.height)
.clipShape(RoundedRectangle(cornerSize: CGSize(width: 10, height: 10), style: .continuous))
.glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 10.0))
} else {
Color
.orange
.clipShape(RoundedRectangle(cornerSize: CGSize(width: 10, height: 10), style: .continuous))
.frame(width: size.width, height: size.height)
}
}
.onAppear{
Task {
try await getImage()
}
}
}
}
}
总结
之前为了解决这个问题使用了各种方法,由于是偶发性的,在使用了SDWebImageSwiftUI,NukeUi,KingFisher等等图片缓存框架后偶尔还是会出现。找了很久都没有找到合适的解决方案。后来想到使用缩略图,通过图片缓存下载后生成缩略图后再渲染,也就省略了所有图片重新上传缩略图了,同时也可以调节缩略图的清晰度。