如何在 Swift 中在 PDF 上绘制内容?

How do I draw something on a PDF in Swift?

这是我目前正在做的事情。

首先,我拿到了文件。接下来我创建一个 PDF 视图并将文档分配给视图。然后我创建一个视图并在视图中进行绘图,然后将视图作为子视图添加到 PDFView。然后我将 PDFView 转换为数据,然后转换为 PDF 文档。由于我在 PDF 的第一页上绘图,我从原始 PDF 中删除了第一页,插入了新的第一页,然后 return 文档。

guard let document = PDFDocument(url: url) else { return nil }
guard let page = document.page(at: 0) else { return nil }
let pageBounds = page.bounds(for: .mediaBox)

let pdfView = PDFView(frame: pageBounds)
pdfView.document = document
pdfView.enclosingScrollView?.autohidesScrollers = true

let view = /// code for subview that I am drawing on
pdfView.addSubview(view)

let data = pdfView.dataWithPDF(inside: pageBounds)
guard let pdf = PDFDocument(data: data) else { return nil }

document.removePage(at: 0)
document.insert(pdf.page(at: 0)!, at: 0)
return document

有更好的方法吗?为了增加皱纹,我的最终产品有一个奇怪的滚动条图像(见屏幕截图)。我尝试添加自动隐藏滚动条和 enclosingScrollView?.hasVerticalScroller = false 但似乎都没有隐藏滚动条。

提前致谢!

所以我已经解决了我自己的问题。对于像我一样卡住的其他人,这就是我所做的。例如在页面上绘制一个框:

  1. 为 PDFDocuments 创建一个 CGContext (ctx)。您可以使用数据或要写入的 URL 来执行此操作。
  2. 使用您要编辑的文档创建一个 CGPDFDocument
  3. 获取要编辑的CGPDF的CGPage(cgPage)

和:

ctx?.beginPDFPage(nil)
ctx?.drawPDFPage(cgPage)
ctx?.beginPath()
let path = CGPath(roundedRect: box as CGRect, cornerWidth: 5, cornerHeight: 5, transform: nil)
ctx?.setStrokeColor(CGColor.black)
ctx?.setFillColor(color.cgColor)
ctx?.setLineWidth(10.0)
ctx?.addPath(path)
ctx?.strokePath()
ctx?.addPath(path)
ctx?.fillPath()
ctx?.endPDFPage()
ctx?.closePDF()

(如果您使用 URL 创建上下文,关闭将写入磁盘。否则您将不得不对 PDF 数据执行某些操作。)

PDFKit 上的 2017 WWDC 视频演示了一个简单的解决方案。我假设您有一个要添加一些绘图的现有文档。要做的是:

  1. 给文档一个委托。

  2. 在委托中,实现 classForPage 为您的页面声明一个 class:class 应该是您自己的 PDFPage subclass。

  3. 在您的 PDFPage 子 class 中,实施 draw(with:to:)。给你一个上下文;画进去!如果您希望默认绘图发生,请务必调用 super

如果你的 PDFPage subclass 需要在不同的页面绘制不同的东西,它可以通过请求 self.document?.index(for:self).

来找出它在文档中的位置