Search code examples
swiftpdfkitios16.4

How do I avoid crash on PDFPage(image: image) with reason EXC_BAD_ACCESS (KERN_INVALID_ADDRESS) on iOS 16+


Same code is working fine on below iOS 16, but crash was observed on higher versions.

Line of Code :

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
}

  • Tried same code on different project, and it's working fine, but it's crashing on client project.
  • Image is not nil
  • Tried with image from xcasset
  • Tried with removing alpha
  • Tried with enabling zombie object

Crash Reason :

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:) ()

Most of similar code base : https://github.com/ShashikantBhadke/PDFKit_Crash_CodeBase


Solution

  • Update your getErrorImageView() method with below code

    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
    }
    

    Since your crash log suggests on creating PDFPage it checks for is_image_alpha_opaque or not. And this provided image is not opaque it will crash. Here since UIGraphicsImageRenderer now takes UIGraphicsImageRendererFormat as input parameter. We can utilise it's ability to for drawHierarchy where we have set its opaque property to true and doesn't updated any alpha.

    I hope this will avoid the crash. Happy Coding ✌️