Swift/SwiftUI iOS迭代写入多张图片到Documents文件夹内存溢出问题咨询
问题原因分析
- 核心原因是批量处理图片过程中产生的UIImage、JPEG数据流等临时对象都堆积在自动释放池中,要等整个循环执行完成后才会统一释放,几千张图片的临时资源累积直接导致内存占用飙升,最终触发分配失败。
- 你当前使用的全量加载原图再缩放的逻辑会额外占用大量内存,单张4000*3000的原图解压后就占接近48MB内存,多几张就会把内存吃满。
- JPEG写入时设置的压缩质量为1.0,生成的文件数据体积过大,进一步加剧内存占用。
可行解决方案
1. 循环内添加自动释放池即时释放临时资源
在最内层的单张图片处理逻辑外层包裹@autoreleasepool,每处理完一张图片就直接释放对应的临时对象,从根源解决内存累积问题,修改后的genThumbnails逻辑如下:
func genThumbnails() -> Void { // 放到后台队列处理,避免卡住主线程 DispatchQueue.global(qos: .utility).async { [weak self] in guard let self = self else { return } for ind in self.foldersData.subDirNames.indices { for indd in self.foldersData.galContents[ind].indices { // 单张图片处理逻辑全放进自动释放池 @autoreleasepool { let imgPath = self.foldersData.galContents[ind][indd] let dirPath: String if self.foldersData.subDirNames[ind] == "Root Folder" { dirPath = NSHomeDirectory().appending("/Documents/Thumbnails/") } else { dirPath = NSHomeDirectory().appending("/Documents/Thumbnails/" + self.foldersData.subDirNames[ind]) } // 优先用优化后的缩略图生成方法,不要先加载全图 if let thumbnail = self.generateThumbnail(path: imgPath, maxSize: max(FoldersViewModel.imageSize[0]/4, FoldersViewModel.imageSize[1]/4)) { _ = self.foldersData.genThumbnailFiles(thumbnail, filename: (imgPath as NSString).lastPathComponent, directoryPath: dirPath) } self.counts[0] = self.counts[0] + 1 } } self.counts[1] = self.counts[1] + 1 } DispatchQueue.main.async { self.foldersData.isLoading = false } } }
2. 用ImageIO优化缩略图生成逻辑
不加载全量原图,直接从文件读取时生成指定尺寸的缩略图,内存占用可以降低90%以上,示例代码:
func generateThumbnail(path: String, maxSize: CGFloat) -> UIImage? { guard let url = URL(fileURLWithPath: path) as CFURL?, let imageSource = CGImageSourceCreateWithURL(url, nil) else { return nil } let options: [CFString: Any] = [ kCGImageSourceCreateThumbnailFromImageAlways: true, kCGImageSourceThumbnailMaxPixelSize: maxSize, kCGImageSourceCreateThumbnailWithTransform: true ] guard let cgThumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary) else { return nil } return UIImage(cgImage: cgThumbnail) }
3. 调整JPEG压缩参数
将jpegData(compressionQuality: 1.0)改为compressionQuality: 0.7,肉眼几乎看不出画质差异,但生成的文件体积可以减少70%左右,写入时的内存占用也会大幅降低。
4. 优化数据存储逻辑
不要在galContents数组中存储全量UIImage对象,仅存储图片的本地文件路径,需要用到的时候再读取,避免不必要的内存占用。
内容的提问来源于stack exchange,提问作者seyitliyev
相关产品推荐
相关产品推荐

