使用PDFOutline在Swift / Cocoa中将TOC添加到PDFDocument

时间:2018-08-04 21:00:03

标签: swift cocoa pdf-generation

我正在研究一个小的例程,该例程需要多个单页PDF,并将它们合并为一个多页PDF。我在Swift4 / MacOS / Cocoa中工作,我一生都找不到在Swift中创建轮廓/仅遍历现有轮廓(我很熟悉)的示例。

使用对文档的最佳猜测,我想到了以下内容,我一直在挥霍一下,但一点也不幸运。 PDF可以很好地显示,但其中永远没有大纲/目录。它可能就像缺少任务一样简单,...任何潜在客户将不胜感激。

顺便说一句,它出现在两个循环中而不是一个循环中的原因是因为我认为也许我需要先添加所有页面-但是尝试并没有什么不同。如果可能的话,最终将只有一个循环。

static func mergePagesIntoSinglePDF(streamId: String, numPages: Int)
    {
        let newPDF = PDFDocument()
        var directoryURLStr = ""

        for pageNum in 1...numPages {

            let directoryUrl = getFileURL(streamId: streamId, recNum: pageNum)
            directoryURLStr = directoryUrl!.absoluteString

            if let pdfDocument = PDFDocument(url: directoryUrl!),
                let pdfPage = pdfDocument.page(at: 0)
            {
                newPDF.insert(pdfPage, at: newPDF.pageCount)    
            }
        }

        for pageNum in 1...numPages {

            let newDest:PDFDestination = PDFDestination.init(page: newPDF.page(at: pageNum-1)!, at:NSPoint(x:1,y:1))
            let newTOCEntry:PDFOutline = PDFOutline.init()

            newTOCEntry.destination = newDest
            newTOCEntry.label = "This is page: \(pageNum)"
            newPDF.outlineRoot?.insertChild(newTOCEntry, at: pageNum-1)
        }

        directoryURLStr = (getFileURL(streamId: streamId)?.absoluteString)!
        let fileURL = URL(string: directoryURLStr)

        newPDF.write(to: fileURL!)
    }

1 个答案:

答案 0 :(得分:0)

似乎我比我想像的要近得多。主要问题是我需要为PDFOutline创建一个根节点。我还添加了一些使NSPoint更加智能的方法,因为您不能在PDF中真正假设“ 1,1” hack是有效的坐标(通常是……但不能假设)。当然,现在可以删除双循环了,但是为了清楚起见,我将其留在了:

static func mergePagesIntoSinglePDF(streamId: String, numPages: Int)
{
    let newPDF = PDFDocument()

    newPDF.outlineRoot = PDFOutline();  // CREATE PDF OUTLINE ROOT NODE!

    var directoryURLStr = ""

    for pageNum in 1...numPages {

        let directoryUrl = getFileURL(streamId: streamId, recNum: pageNum)
        directoryURLStr = directoryUrl!.absoluteString

        if let pdfDocument = PDFDocument(url: directoryUrl!),
            let pdfPage = pdfDocument.page(at: 0)
        {
            newPDF.insert(pdfPage, at: newPDF.pageCount)    
        }
    }

    for pageNum in 1...numPages {

        let pdfPage = newPDF.page(at: pageNum-1)!

        // ADD A LITTLE CODE TO MAKE THE NSPoint IN THE DESTINATION MORE SOUND

        let pdfPageRect = pdfPage.bounds(for: PDFDisplayBox.mediaBox)
        let topLeft = NSMakePoint(pdfPageRect.minX, pdfPageRect.height + 20)
        let destination = PDFDestination(page: pdfPage, at: topLeft)

        let newDest = PDFDestination(page: pdfPage, at:topLeft)
        let newTOCEntry = PDFOutline()

        newTOCEntry.destination = newDest
        newTOCEntry.label = "\(streamId) page \(pageNum)"
        newPDF.outlineRoot!.insertChild(newTOCEntry, at: pageNum-1)
    }

    directoryURLStr = (getFileURL(streamId: streamId)?.absoluteString)!
    let fileURL = URL(string: directoryURLStr)

    newPDF.write(to: fileURL!)
}