如何避免在 iOS 16+ 上因 EXC_BAD_ACCESS (KERN_INVALID_ADDRESS) 而导致 PDFPage(image: image) 崩溃

问题描述 投票:0回答:2

相同的代码在 iOS 16 以下版本上运行良好,但在更高版本上观察到崩溃。

代码行:

if let errorView = getErrorImageView(),
            let page = PDFPage(image: errorView) { // <- Crash Observed on this line.
            page.addAnnotation(getTitlePDFAnnotation())
            let count = pdfDocument?.pageCount ?? 0
            pdfDocument?.insert(page, at: count)
        }


fun getErrorImageView() -> UIImage? {
let errorView = UIView()
        errorView.bounds = view.bounds
        errorView.backgroundColor = .athenaWhite
        let errorTitleLabel = UILabel()
        errorTitleLabel.translatesAutoresizingMaskIntoConstraints = false
        errorTitleLabel.text = "Error"
        errorTitleLabel.textAlignment = .center
        errorView.addSubview(errorTitleLabel)
        // .... added constraint to view
let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
        let image = renderer.image { _ in
            errorView.drawHierarchy(in: errorView.bounds, afterScreenUpdates: true)
        }
        return image
}

  • 在不同的项目上尝试了相同的代码,并且工作正常,但在客户端项目上崩溃了。
  • 图像不为零
  • 尝试使用 xcasset 中的图像
  • 尝试删除阿尔法
  • 尝试启用僵尸对象

崩溃原因:

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

#0  0x000000012084d25f in CGBlitInternal::cgsBufferIsConstantValue_internal::TestLimits<unsigned char, 64ul>::operator()(unsigned char const*, unsigned long, CGBlitInternal::cgsBufferIsConstantValue_internal::Limits const&) ()
#1  0x0000000120b89921 in bool CGBlitInternal::cgsBufferIsConstantValue_internal::TestLimitsRow<unsigned char>(void const*, unsigned long, CGBlitInternal::cgsBufferIsConstantValue_internal::Limits const&) (.10518) ()
#2  0x0000000120b8969d in bool CGBlitInternal::CGBufIsConstantValue<(CGBlitVariant)0>(CGBuf const*, float const*, float const*) ()
#3  0x0000000120ba7fe4 in is_image_alpha_opaque ()
#4  0x0000000120ba7bb8 in create_jpeg_copy ()
#5  0x0000000120bbd1df in pdf_DrawImage ()
#6  0x0000000120ad32b8 in CGContextDrawImageWithOptions ()
#7  0x00000001207e2ad2 in CGPDFPageCreateWithImage ()
#8  0x000000012b9c9e44 in +[PDFPage _createPageRefFromImage:andOptions:] ()
#9  0x000000012b9c38dd in -[PDFPage initWithCGImage:options:] ()
#10 0x000000012b9c476f in -[PDFPage initWithImage:options:] ()
#11 0x000000012b9c45ae in -[PDFPage initWithImage:] ()
#12 0x000000010502f913 in @nonobjc PDFPage.init(image:) ()
#13 0x0000000105025232 in PDFPage.__allocating_init(image:) ()

大多数类似的代码库:https://github.com/ShashikantBhadke/PDFKit_Crash_CodeBase

swift pdfkit ios16.4
2个回答
1
投票

使用以下代码更新您的 getErrorImageView() 方法

fun getErrorImageView() -> UIImage? {
    let errorView = UIView()
    errorView.bounds = view.bounds
    errorView.backgroundColor = .white
    let errorTitleLabel = UILabel()
    errorTitleLabel.translatesAutoresizingMaskIntoConstraints = false
    errorTitleLabel.text = "Error"
    errorTitleLabel.textAlignment = .center
    errorView.addSubview(errorTitleLabel)
    // .... added constraint to view
    // Create a UIGraphicsImageRendererFormat and set its opaque as true
    let rendererFormat = UIGraphicsImageRendererFormat.default()
    rendererFormat.opaque = true
    // Now pass this rendererFormat to UIGraphicsImageRenderer
    let renderer = UIGraphicsImageRenderer(size: view.bounds.size, format: rendererFormat)
    let image = renderer.image { _ in
        errorView.drawHierarchy(in: errorView.bounds, afterScreenUpdates: true)
    }
    return image
}

由于您的崩溃日志建议创建

PDFPage
,因此它会检查是否存在
is_image_alpha_opaque
。而且这个提供的图像不是不透明的,它会崩溃。 因为
UIGraphicsImageRenderer
现在将
UIGraphicsImageRendererFormat
作为输入参数。 我们可以利用它的功能来绘制层次结构,我们将其
opaque
属性设置为 true 并且不更新任何
alpha

我希望这能避免崩溃。快乐编码✌️


0
投票

另一种解决方法,为了避免图像不透明问题,您需要首先使用不透明的格式绘制图像并使用标准颜色范围,然后在 PDF 上下文中绘制新图像。

// Re-draw image to adjust color range etc.
let format = UIGraphicsImageRendererFormat.default()
format.preferredRange = .standard
format.opaque = true
format.scale = 1
let newImage = UIGraphicsImageRenderer(size: image.size, format: format).image { _ in
    image.draw(in: CGRect(origin: .zero, size: image.size))
}

// Draw in PDF context
newImage.draw(in: CGRect(origin: .zero, size: newImage.size))

参考自:https://developer.apple.com/forums/thread/736607

© www.soinside.com 2019 - 2024. All rights reserved.