iOS 15下Swift 4使用PDFKit PDFDocument渲染含公式PDF异常问题
问题产生原因
- iOS 15 对PDFKit的字体嵌入逻辑做了不兼容改动:iOS 14及更低版本中,从PDFDocument中拆分单页导出时,系统会自动将当前页依赖的自定义字体(包括公式常用的TeX字体、Type3字体)嵌入到导出的单页PDF文件中,而iOS 15为了压缩导出文件体积,默认关闭了自动嵌入逻辑,仅保留字体引用。公式类内容依赖的特殊数学字体并未内置在iOS系统中,缺失字体后就会出现公式数值空白的异常。
- PDFKit 渲染优化缺陷:iOS 15新增的PDF渲染缓存机制会优先匹配系统内置字体,忽略PDF文件内嵌的字形信息,进一步导致公式的矢量字形无法被正确绘制。
- 原有代码存在逻辑疏漏:你提供的代码中获取PDFPage实例后,并未使用官方提供的单页导出接口生成PDF数据,而是直接使用了来源不明的
pagePdfBase64变量,同时存在多余的Data转Base64再解码的无效操作,本身就存在资源丢失、崩溃的风险。
适配修复方案
优先选择无私有API、全版本兼容的手动绘制方案,修复后代码如下:
urlSession.dataTask(with: pagesRequest) { (data, response, error) in guard let data = data, let document = PDFDocument(data: data) else { return } let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] for count in 0..<document.pageCount { guard let page = document.page(at: count) else { continue } // 获取页面实际尺寸 let pageBounds = page.bounds(for: .mediaBox) // 用CoreGraphics手动绘制单页,强制携带所有字体、矢量资源 let renderer = UIGraphicsPDFRenderer(bounds: pageBounds) let pdfData = renderer.pdfData { context in context.beginPage() page.draw(with: .mediaBox, to: context.cgContext) } // 写入文件 let fileName = "\(self.folderName)/\(count + 1).pdf" let fileUrl = URL(fileURLWithPath: documentsPath).appendingPathComponent(fileName) do { try pdfData.write(to: fileUrl) } catch { print("文件写入失败: \(error)") } } }
如果不想改动现有导出逻辑,可针对iOS 15+系统全局关闭PDFKit新字体渲染特性,注意需在初始化PDFDocument前调用:
if #available(iOS 15.0, *) { UserDefaults.standard.set(false, forKey: "PDFKitEnableNewFontRendering") UserDefaults.standard.synchronize() }
如果是PDF显示阶段出现的异常,可在PDFView加载完成后强制重绘当前页:
if #available(iOS 15.0, *) { pdfView.currentPage?.draw(with: .mediaBox, to: pdfView.context!) }
内容的提问来源于stack exchange,提问作者Rodrigo Lima
相关产品推荐
相关产品推荐

