0

我正在尝试构建一个通用类来在 macOSiOS 中创建 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
}
4

0 回答 0