【发布时间】:2019-09-04 22:05:23
【问题描述】:
我有一个过程,它采用 HTML 字符串数组并使用以下方法逐页构建 PDF:
let printPageRenderer = ReportPrintPageRenderer(withTemplate: self.template)
var pageIndex = 0
data.forEach { (htmlPage) in
let printFormatter = UIMarkupTextPrintFormatter(markupText: htmlPage)
printPageRenderer.addPrintFormatter(printFormatter, startingAtPageAt: pageIndex)
pageIndex += 1
}
let pdfData = drawPDFUsingPrintPageRendererNoImages(printPageRenderer: printPageRenderer)
drawPDFUsing... 方法使用了我见过多次描述的标准方法:
let data = NSMutableData()
UIGraphicsBeginPDFContextToData(data, CGRect.init(x: 0, y: 0, width: template.pageWidth, height: template.pageHeight), nil)
printPageRenderer.prepare(forDrawingPages: NSMakeRange(0, printPageRenderer.numberOfPages))
let bounds = UIGraphicsGetPDFContextBounds()
for i in 0...((printPageRenderer.numberOfPages - 1 < 0) ? 0 : printPageRenderer.numberOfPages - 1) {
UIGraphicsBeginPDFPage()
printPageRenderer.drawPage(at: i, in: bounds)
}
UIGraphicsEndPDFContext()
return data
整个过程完美运行,直到我获得大约 130 页长的 PDF 文档。在模拟器中,我可以毫无问题地打印超过 250 页的文档。但是,对于实际设备(iPhone x 或 iPad pro)上的相同数据,data.forEach 循环会一直运行,直到 pageIndex 达到大约 130,然后它会在此行显示以下信息失败:
let printFormatter = UIMarkupTextPrintFormatter(markupText: htmlPage)
Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1aa2b0330)
warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available.
没有其他异常产生
内存使用量还可以,虽然它已经飙升,但考虑到我正在做的事情,它似乎并不过分。此外,在模拟器中运行时它会像这样增加,并且通常只有 300-400MB 左右的峰值。
我尝试了以下方法来解决这个问题,但都没有成功:
- 将进程的各个部分包装在 autoreleasepool 中
- 通过在处理数据时随机化数据来确保它不是我的 HTML 数据字符串。无论订单如何,它总是在 130 条记录后失败
- 切换到 iOS13
- 更改将每个页面作为单独的 PDF 写入磁盘的过程。不管我怎么做,创建130个页面后仍然总是失败
我不知所措,因为它正在发生什么,并且不知道如何解决这个问题。任何想法或帮助将不胜感激。
根据 cmets 中的建议,这是在调试器中运行 bt 的跟踪:
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1aa326a14)
frame #0: 0x00000001aa326a14 WebCore`bmalloc::IsoAllocator<bmalloc::IsoConfig<88u> >::allocateSlow(bool) + 252
frame #1: 0x00000001aaaf7f48 WebCore`WebCore::RenderText::createTextBox() + 28
frame #2: 0x00000001aab06e90 WebCore`WebCore::RenderTextLineBoxes::createAndAppendLineBox(WebCore::RenderText&) + 40
frame #3: 0x00000001aa9e2c50 WebCore`WebCore::RenderBlockFlow::constructLine(WebCore::BidiRunList<WebCore::BidiRun>&, WebCore::LineInfo const&) + 344
frame #4: 0x00000001aa9e5944 WebCore`WebCore::RenderBlockFlow::createLineBoxesFromBidiRuns(unsigned int, WebCore::BidiRunList<WebCore::BidiRun>&, WebCore::InlineIterator const&, WebCore::LineInfo&, WebCore::VerticalPositionCache&, WebCore::BidiRun*, WTF::Vector<WebCore::WordMeasurement, 64ul, WTF::CrashOnOverflow, 16ul>&) + 100
frame #5: 0x00000001aa9e825c WebCore`WebCore::RenderBlockFlow::layoutRunsAndFloatsInRange(WebCore::LineLayoutState&, WebCore::BidiResolverWithIsolate<WebCore::InlineIterator, WebCore::BidiRun, WebCore::BidiIsolatedRun>&, WebCore::InlineIterator const&, WebCore::BidiStatus const&, unsigned int) + 4576
frame #6: 0x00000001aa9e5e2c WebCore`WebCore::RenderBlockFlow::layoutRunsAndFloats(WebCore::LineLayoutState&, bool) + 920
frame #7: 0x00000001aa9ea03c WebCore`WebCore::RenderBlockFlow::layoutLineBoxes(bool, WebCore::LayoutUnit&, WebCore::LayoutUnit&) + 1800
frame #8: 0x00000001aa9cd5cc WebCore`WebCore::RenderBlockFlow::layoutBlock(bool, WebCore::LayoutUnit) + 1056
frame #9: 0x00000001aaadad84 WebCore`WebCore::RenderTableCell::layout() + 196
frame #10: 0x00000001aaae8794 WebCore`WebCore::RenderTableRow::layout() + 252
frame #11: 0x00000001aaaea914 WebCore`WebCore::RenderTableSection::layout() + 844
frame #12: 0x00000001aaacf744 WebCore`WebCore::RenderTable::layout() + 1916
frame #13: 0x00000001aa9cf578 WebCore`WebCore::RenderBlockFlow::layoutBlockChild(WebCore::RenderBox&, WebCore::RenderBlockFlow::MarginInfo&, WebCore::LayoutUnit&,
.....
如果我将其剥离为最基本的要素,甚至不尝试创建 PDF:
func exportHTMLContentToPDFNoImages(reportName name:String, fromHTMLData data: [String]) throws -> URL? {
data.shuffled().forEach { (htmlPage) in
autoreleasepool { () -> Void in
let _ = UIMarkupTextPrintFormatter(markupText: htmlPage)
}
}
return nil
}
在第 130 次通过循环后它仍然崩溃。用一些简单的 html 替换 htmlPage,例如
<html><body>Hi</body></html>
工作得很好。因此,我正在创建的表中一定存在导致问题的内容。
更新
我能够将其简化为一个非常简单的示例,向我证明这是 iOS 中的一个错误。我也最终向苹果报告了它。幸运的是,这个 bug 看起来在 13.1 中已经修复,所以即使 iOS 12 存在问题,未来也有前进的道路。
【问题讨论】:
-
从 Xcode 连接到设备时,您能否重现该问题?如果是这样,您可以提供堆栈跟踪吗?如果发生异常时 Xcode 没有停止,请确保您启用了 Exception Breakpoints。见stackoverflow.com/a/17802723/196964
-
以上信息来自Xcode所附的设备。我没有得到堆栈跟踪或任何有用的东西。只是自动中断调试器,突出显示该行和第一条错误消息。调试控制台有第二条消息。不幸的是,这真的没有太多信息。
-
如果你打开 lldb 调试器并运行
bt来获取堆栈跟踪呢? stackoverflow.com/a/26770913/196964 -
谢谢...不知道那个。我更新了我的答案。仍然不确定发生了什么,但也许你会