相同的代码在 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
}
崩溃原因:
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
使用以下代码更新您的 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
。
我希望这能避免崩溃。快乐编码✌️
另一种解决方法,为了避免图像不透明问题,您需要首先使用不透明的格式绘制图像并使用标准颜色范围,然后在 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))