swift - 同一 PDF 的多页 View

标签 swift pdf macos-sierra

我正在使用 PDFKit(快速编程语言,macOS)中的 PDFView 来显示一些 PDF 文档。 我想显示同一个 PDF 的多个页面。 一种解决方案是从同一个 PDF 创建多个 PDFView,但这样我必须多次分配相同的内存,这对于图像丰富的 PDF 来说可能是个问题。 有没有什么快速的方法可以在 4/8 不同的 View 中显示同一 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)!)
        }
    }
}

最佳答案

PDFView很可能无法很好地用于显示同一 PDF 文档的多个页面。

但是你可以自己做。 PDFPage 可以将自身绘制到任何给定的图形上下文。您可以创建 NSView 的子类来绘制页面或使用其他更奇特的 View (如 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)
    }
}

重要提示:您需要在绘制之前转换 View 的上下文以适合页面并弥补任何页面旋转。 PDFPage 对此有一些帮助函数。

另请注意,draw(with box: PDFDisplayBox, to context: CGContext) 从 MacOS 10.12 开始,要支持以前的版本,请使用 draw(with box: PDFDisplayBox)

在您的 Controller 中,加载 PDF 文档并将每个页面分配给需要显示它的 View 。

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 页面时,页面绘制不遵守 View 的边界。自己试试吧,你会明白我的意思。您需要自己对上下文进行缩放,通常是将当前图形上下文转换为所需的坐标。搜索 Cocoa Drawing Guide 以获取有关上下文和转换的详细信息。 PDFPage 提供了一些辅助方法,让您可以获取原始页面边界和页面可能用于旋转页面的转换(如果需要)。

要获取页面的矩形,您可以使用边界(对于框:PDFDisplayBox),而不是上下文大小。在使用它之前,您需要转换上下文。但这都在文档中,你真的需要阅读 Cocoa/Quartz 绘图指南和 PDF 页面的文档。所以一定要看看那里。

关于swift - 同一 PDF 的多页 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40247438/

相关文章:

IOS Swift 二元运算符 '<=' 不能应用于类型为 'CGFloat?' 和 'Int' 的操作数,但 '==' 有效

ruby-on-rails - 使用Rails邮件程序 Prawn PDF?

Vim 的 'dot-separated' 双文件类型时尚

c - poll() 在 macOS 上为超过 256 个描述符返回 EINVAL

swift - 在 Swift 中将协议(protocol)转换为类

ios - 在 Mapbox iOS SDK 中将 map 移动到标记下

c# - 将网页导出为 pdf 时从代码隐藏进行自定义

php - TCPDF 无法显示西里尔字母

java - SoftLayer SSL VPN 门户 java.lang.NullPointerException @macOS Sierra

iOS实现导航类(class)不保存