iOS15修改PDF时插入新图片导致旧图片被覆盖问题咨询
问题结论
这是iOS 15的已知系统级缓存Bug,同时你的实现逻辑存在可优化的疏漏,两者共同导致了问题出现。
问题原因
- 你当前的实现采用了读写同路径的逻辑:调用
UIGraphicsBeginPDFContextToFile时直接指定了原PDF的存储路径,相当于一边读取同一路径下的PDF内容,一边对该文件进行覆盖写入。 - iOS 15对
CGPDFDocument新增了内存缓存优化逻辑:当读取的PDF文件路径不变时,系统会复用首次读取的页面缓存,不会主动拉取磁盘上的最新内容。因此你循环处理页面时,读取到的第二页是第一次修改前的缓存内容,之前插入的第二张图自然就丢失了。 - iOS 14及更早版本没有这项缓存逻辑,每次读取页面都会从磁盘拉取最新内容,所以相同代码可以正常运行。
修复方案
你可以任选以下任意一种方案规避问题:
方案1:读写路径分离(推荐)
先将修改后的PDF写入临时文件路径,所有内容写入完成后,再用临时文件覆盖原路径的PDF,从根源上避免读写同个文件触发缓存:
func saveImageToPDF(path: String , drawnImage: UIImage, x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat, pageIndex: Int) { guard let pdf = CGPDFDocument(NSURL(fileURLWithPath: path)) else { return } let pageCount = pdf.numberOfPages // 生成临时写入路径 let tempPath = NSTemporaryDirectory() + UUID().uuidString + ".pdf" UIGraphicsBeginPDFContextToFile(tempPath, CGRect.zero, nil) for index in 1...pageCount { guard let page = pdf.page(at: index), let pageFrame = page.getBoxRect(.mediaBox) as? CGRect else { continue } UIGraphicsBeginPDFPageWithInfo(pageFrame, nil) guard let pdfContext = UIGraphicsGetCurrentContext() else { continue } // 绘制原有页面内容 pdfContext.saveGState() pdfContext.scaleBy(x: 1, y: -1) pdfContext.translateBy(x: 0, y: -pageFrame.size.height) pdfContext.drawPDFPage(page) pdfContext.restoreGState() // 绘制新图片 if index == (pageIndex + 1) { drawnImage.draw(in: CGRect(x: x, y: y, width: width, height: height)) } } UIGraphicsEndPDFContext() // 写入完成后用临时文件覆盖原文件 do { try FileManager.default.removeItem(atPath: path) try FileManager.default.moveItem(atPath: tempPath, toPath: path) } catch { print("文件替换失败: \(error.localizedDescription)") } }
方案2:用Data初始化CGPDFDocument
读取原PDF时先把文件内容加载为内存Data,再用Data初始化CGPDFDocument,绕过系统对磁盘文件的缓存逻辑。
内容的提问来源于stack exchange,提问作者Scout 43
相关产品推荐
相关产品推荐

