我正在使用PDFKit(swift编程语言,macOS)中的PDFView来显示一些PDF文档。 我想显示相同PDF的多个页面。 一个解决方案是从同一个PDF创建多个PDFView,但是这样我必须多次分配相同的内存,这对于富含图像的PDF来说可能是一个问题。 有没有快速的方法可以在4/8种不同的视图中显示相同PDF的不同页面?
编辑: @danielv的宝贵建议带来了这段代码
import Cocoa
import Quartz
class PDFPageView: NSView {
var pdfPage: PDFPage?
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
if(pdfPage != nil) {
let context = NSGraphicsContext.current()
let pdfBox = PDFDisplayBox.mediaBox
let pdfBounds = pdfPage?.bounds(for: pdfBox)
let scaleX = visibleRect.width/(pdfBounds?.width)!
let scaleY = visibleRect.height/(pdfBounds?.height)!
let scale = min(scaleX,scaleY)
context?.cgContext.scaleBy(x: scale, y: scale)
pdfPage?.draw(with: pdfBox, to: (context?.cgContext)!)
}
}
}
答案 0 :(得分:1)
PDFView
很可能不会很好地用于显示同一PDF文档的多个页面。
但你可以自己动手。 PDFPage
可以将自己绘制到任何给定的图形上下文中。您可以创建NSView
的子类来绘制页面或使用其他更奇特的视图,如NSCollectionView
,并将页面绘制到其行/列/网格。
以下是关于如何使用NSView进行的操作:
创建NSView的子类
class PDFPageView: NSView {
var pdfPage: PDFPage?
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
let context = NSGraphicsContext.current()!
pdfPage?.draw(with: .mediaBox, to: context.cgContext)
}
}
重要事项:您需要在绘制之前转换视图的上下文以适应页面并弥补任何页面轮换。 PDFPage
有一些帮助函数。
另请注意,draw(with box: PDFDisplayBox, to context: CGContext)
是自MacOS 10.12以来支持以前的版本使用draw(with box: PDFDisplayBox)
在控制器中,加载PDF文档并将每个页面分配给需要显示它的视图。
class ViewController: NSViewController {
@IBOutlet weak var pdfPageView: PDFPageView?
var pdfDocumenet: PDFDocument?
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(fileURLWithPath: "... pdf filename ...")
pdfDocumenet = PDFDocument(url: url)
pdfPageView?.pdfPage = pdfDocumenet?.page(at: 0)
}
}
编辑(包括作者的评论):
当您尝试在NSView的上下文中绘制PDF页面时,页面绘图不符合视图的界限。亲自尝试一下,你会明白我的意思。您需要自己进行上下文缩放,通常是将当前图形上下文转换为所需的坐标。搜索Cocoa绘图指南,了解有关上下文和转换的详细信息。 PDFPage提供了一些帮助方法,可以让您获取原始页面边界以及页面可能用于旋转页面的转换(如果需要)。
要获取页面的rect,您可以使用bounds(对于box:PDFDisplayBox),而不是上下文大小。您需要在绘制上下文之前转换上下文。但这完全在文档中,你真的需要阅读Cocoa / Quartz绘图指南和PDF页面的文档。所以一定要看看那里。