问题描述
我正在使用Swift 5和iOS。我正在尝试将文本覆盖到当前的PDF上。我实质上是在移植从macOS应用程序制作的代码。这是Mac版本的代码:
func executeContext(at srcURL: URL,to dstURL: URL) {
// Confirm there is a document there
if let doc: PDFDocument = PDFDocument(url: srcURL) {
// Create a document,get the first page,and set the size of the page
let page: PDFPage = doc.page(at: 0)!
var mediaBox: CGRect = CGRect(x: 0,y: 0,width: 792,height: 612)
// This is where the magic happens. Create the drawing context on the PDF
let context = CGContext(dstURL as CFURL,mediaBox: &mediaBox,nil)
let graphicsContext = NSGraphicsContext(cgContext: context!,flipped: false)
NSGraphicsContext.current = graphicsContext
context!.beginPDFPage(nil)
// Draws the PDF into the context
page.draw(with: .mediaBox,to: context!)
// Parse and Draw Text on the context
//drawText()
let attributes = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 72)
]
let text = "I'm a PDF!"
text.draw(at: CGPoint(x: 0,y: 0),withAttributes: attributes)
context!.saveGState()
context!.restoreGState()
context!.endPDFPage()
NSGraphicsContext.current = nil
context?.closePDF()
}
}
drawText()
函数完成了大多数所需的文本叠加,但是我在其下面放置了另一种“绘制”方法来进行测试。
我可以理解的是,由于iOS上不存在NSGraphicsContext,因此出现了一个错误Cannot find 'NSGraphicsContext' in scope
。我试图用UIGraphicsPDFRenderer或UIGraphicsBeginPDFContextToData找到等效的翻译,并使用Ray Wenderlich tutorial中的一些代码,我能够创建一个新的PDF并使用以下代码在其上放置文本:
func createDocument(url: URL) -> Data {
//let pdfData = try? Data.init(contentsOf: url)
// 1
let pdfMetaData = [
kCGPDFContextCreator: "Timecard App",kCGPDFContextAuthor: "Timecard App"
]
let format = UIGraphicsPDFRendererFormat()
format.documentInfo = pdfMetaData as [String: Any]
// 2
let pageWidth = 8.5 * 72.0
let pageHeight = 11 * 72.0
let pageRect = CGRect(x: 0,width: pageWidth,height: pageHeight)
// 3
let renderer = UIGraphicsPDFRenderer(bounds: pageRect,format: format)
// 4
let data = renderer.pdfData { (context) in
// 5
context.beginPage()
// 6
let attributes = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 72)
]
let text = "I'm a PDF!"
text.draw(at: CGPoint(x: 0,withAttributes: attributes)
}
return data
}
...但是我找不到将当前PDF“数据”加载到渲染器然后从那里进行绘制的方法。有人对执行此操作的正确方法有任何建议吗?
解决方法
这里是可能的解决方案-实际上,您只需要直接与CoreGraphics上下文一起操作,设置当前值,进行翻转变换等即可(保留原始代码的样式和约定)。
通过Xcode 12 / iOS 14测试。
func executeContext(at srcURL: URL,to dstURL: URL) {
// Confirm there is a document there
if let doc: PDFDocument = PDFDocument(url: srcURL) {
// Create a document,get the first page,and set the size of the page
let page: PDFPage = doc.page(at: 0)!
var mediaBox: CGRect = page.bounds(for: .mediaBox)
// This is where the magic happens. Create the drawing context on the PDF
let context = CGContext(dstURL as CFURL,mediaBox: &mediaBox,nil)
UIGraphicsPushContext(context!)
context!.beginPDFPage(nil)
// Draws the PDF into the context
page.draw(with: .mediaBox,to: context!)
let flipVertical: CGAffineTransform = CGAffineTransform(a: 1,b: 0,c: 0,d: -1,tx: 0,ty: mediaBox.size.height)
context!.concatenate(flipVertical)
let attributes = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 72)
]
let text = "I'm a PDF!"
text.draw(at: CGPoint(x: 0,y: 0),withAttributes: attributes)
context!.endPDFPage()
context?.closePDF()
UIGraphicsPopContext()
}
}