我正在尝试构建一个通用类来在 macOS和iOS 中创建 pdf 文件(这就是为什么不能使用 usingUIGraphicsPDFRenderer
的原因)。为了跨平台兼容,我必须坚持使用 Apple 的PDFKit
.
当前创建 pdf 失败并出现我不明白的错误:
failed to find start of cross-reference table.
missing or invalid cross-reference trailer.
这在 macOS 和 iOS 上运行时会出现(后者仅CG_PDF_VERBOSE
在运行方案中设置了环境变量时才奇怪......)
我正在尝试使用PDFDocument(data:)
. 现在,我知道根据这个 init 的文档“数据必须是封装在 NSData 对象中的 PDF 数据;否则此方法返回 NULL。” - 但据我所知,这就是我正在尝试的(我希望有人会证明我错了……)。
这是代码:
enum PdfError: Error {
case dataConsumerError, pdfContextError, pdfDocumentError, pdfPageError
}
static func getPdf(from text: String) throws -> PDFDocument {
let attrString = NSAttributedString(string: text)
let framesetter = CTFramesetterCreateWithAttributedString(attrString)
var pageRange = CFRange()
let paperHeight = 841.89
let paperWidth = 595.28
let margin = 20.0
CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRange(location: 0, length: attrString.length), nil, CGSize(width: paperWidth, height: paperHeight), &pageRange)
let pageRect = CGRect(x: margin, y: margin, width: 595.28 - margin, height: 841.89 - margin)
let framePath = CGPath(rect: pageRect, transform: nil)
let frame = CTFramesetterCreateFrame(framesetter, pageRange, framePath, nil)
let pdfData = NSMutableData()
var mediaBox = CGRect(x: 0, y: 0, width: paperWidth, height: paperHeight)
guard let pdfConsumer = CGDataConsumer(data: pdfData as CFMutableData) else {
throw PdfError.dataConsumerError
}
guard let pdfContext = CGContext(consumer: pdfConsumer, mediaBox: &mediaBox, nil) else {
throw PdfError.pdfContextError
}
pdfContext.beginPDFPage(nil)
CTFrameDraw(frame, pdfContext)
pdfContext.endPDFPage()
let convertedPdfData = pdfData as Data
guard let pdf = PDFDocument(data: convertedPdfData) else { //this is where above mentioned error is printed
throw PdfError.pdfDocumentError
}
return pdf
}