iOS 16调用PDFPage(image)触发EXC_BAD_INSTRUCTION错误求助
解决iOS 16中
PDFPage(image:)崩溃及移除Alpha通道后黑角问题 问题背景
在iOS 16及以上版本中,调用PDFPage(image:)初始化PDF页面时会触发EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)崩溃,这段代码在iOS 16以下版本运行完全正常。
最初尝试通过移除图片的Alpha通道来解决崩溃,但生成的PDF页面出现了大黑角——这是因为设置format.opaque = true后,绘图上下文默认背景为黑色,原图片的透明区域直接显示了黑色背景。
原崩溃代码
extension PDFDocument { func flattened(withDPI dpi: CGFloat = 72) -> PDFDocument { let flattenedDocument = PDFDocument() for pageIndex in 0..<pageCount { let oldPage = page(at: pageIndex) var image = oldPage?.image(withDPI: dpi) if (image != nil) { // iOS 16此处崩溃 let flattenedPage = PDFPage(image: image!) if (flattenedPage != nil) { flattenedDocument.insert(flattenedPage!, at: flattenedDocument.pageCount) } } } return flattenedDocument } }
最初尝试的移除Alpha代码(导致黑角)
extension UIImage { func removeAlpha() -> UIImage { let format = UIGraphicsImageRendererFormat.init() format.opaque = true // 移除Alpha通道 format.scale = scale // 保留原图片缩放比例 let size = size return UIGraphicsImageRenderer(size: size, format: format).image { context in draw(in: CGRect(origin: .zero, size: size)) } } }
修复方案
核心思路:移除Alpha通道前,先给绘图上下文填充白色背景(符合PDF页面的常规底色),再绘制原图片,这样透明区域会被白色填充,不会出现黑角。
修改后的UIImage扩展:
extension UIImage { func removeAlphaWithWhiteBackground() -> UIImage { let format = UIGraphicsImageRendererFormat() format.opaque = true format.scale = scale return UIGraphicsImageRenderer(size: size, format: format).image { context in // 先填充白色背景 UIColor.white.setFill() context.fill(CGRect(origin: .zero, size: size)) // 再绘制原图片 draw(in: CGRect(origin: .zero, size: size)) } } }
修改后的调用逻辑:
extension PDFDocument { func flattened(withDPI dpi: CGFloat = 72) -> PDFDocument { let flattenedDocument = PDFDocument() for pageIndex in 0..<pageCount { guard let oldPage = page(at: pageIndex), var image = oldPage.image(withDPI: dpi) else { continue } // iOS 16及以上版本处理Alpha通道 if #available(iOS 16.0, *) { image = image.removeAlphaWithWhiteBackground() } if let flattenedPage = PDFPage(image: image) { flattenedDocument.insert(flattenedPage, at: flattenedDocument.pageCount) } } return flattenedDocument } }
说明
- 给上下文填充白色背景后,原图片的透明区域会被白色覆盖,解决了黑角问题
- 保留了原图片的缩放比例,避免生成的PDF页面尺寸失真
- 仅在iOS 16及以上版本执行Alpha通道移除逻辑,不影响低版本的正常运行
内容的提问来源于stack exchange,提问作者Malwinder Singh
相关产品推荐
相关产品推荐

