You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 00:00:01