You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI Mac应用:URL转PDFDocument后NSPrintOperation打印排版异常求助

问题:SwiftUI Mac应用打印PDF排版异常,内容截断无法适配纸张宽度

我正在使用SwiftUI开发Mac应用,通过URL获取PDFDocument后,点击按钮用NSPrintOperation打印文档。目前功能能运行,但打印时排版异常,PDF内容被严重截断,像是叠在其他文档上,希望让PDF占满纸张宽度(忽略纸张上原有方框)。测试用PDF链接:https://www.soundczech.cz/temp/lorem-ipsum.pdf

打印异常示意图

现有代码

import SwiftUI
import PDFKit
import AppKit
struct ContentView: View {
    let pdfDocumentUrl = URL(string: "https://www.soundczech.cz/temp/lorem-ipsum.pdf")!

    
    var body: some View {
        VStack {
            Button("Print PDF") {
                let pdf = PDFDocument(url: pdfDocumentUrl)!
                printPDFDocumentt(pdf)
            }
        }
        .padding()
    }
    
    func printPDFDocumentt(_ document: PDFDocument) {
        
        let pdfView = PDFView(frame: .init(x: 0, y: 0, width: document.page(at: 0)?.bounds(for: .mediaBox).width ?? 0,
                                                        height: document.page(at: 0)?.bounds(for: .mediaBox).height ?? 0))
        pdfView.document = document
        pdfView.backgroundColor = .clear
        
        let printInfo = NSPrintInfo.shared
        printInfo.horizontalPagination = .fit
        printInfo.verticalPagination = .fit
        printInfo.orientation = .portrait
        
        let printOperation = NSPrintOperation(view: pdfView, printInfo: printInfo)
        printOperation.run()
    }
}

解决方案

问题根源在于通过PDFView作为打印视图时的适配逻辑缺失,以及NSPrintInfo的配置不够精准。以下是两种可行的修复方案:

方案一:直接调用PDFDocument的打印方法(推荐)

无需手动创建PDFView,利用PDFDocument自带的打印方法,系统会自动处理PDF与纸张的适配逻辑:

func printPDFDocumentt(_ document: PDFDocument) {
    let printInfo = NSPrintInfo.shared
    printInfo.horizontalPagination = .fit
    printInfo.verticalPagination = .fit
    // 根据PDF页面尺寸自动匹配打印方向
    if let firstPage = document.page(at: 0) {
        let pageBounds = firstPage.bounds(for: .mediaBox)
        printInfo.orientation = pageBounds.width > pageBounds.height ? .landscape : .portrait
    }
    // 设置边距为0,让内容尽可能占满纸张
    printInfo.topMargin = 0
    printInfo.bottomMargin = 0
    printInfo.leftMargin = 0
    printInfo.rightMargin = 0
    
    document.print(with: printInfo, displayPrintDialog: true)
}

方案二:调整PDFView的适配配置

如果必须保留PDFView作为打印视图,需要完善其缩放和尺寸设置:

func printPDFDocumentt(_ document: PDFDocument) {
    guard let firstPage = document.page(at: 0) else { return }
    let pageBounds = firstPage.bounds(for: .mediaBox)
    
    let pdfView = PDFView()
    pdfView.document = document
    pdfView.backgroundColor = .clear
    // 开启自动缩放,让PDF适配视图尺寸
    pdfView.autoScales = true
    pdfView.displayMode = .singlePage
    // 设置缩放因子为适配视图的比例
    pdfView.scaleFactor = pdfView.scaleFactorForSizeToFit
    
    let printInfo = NSPrintInfo.shared
    printInfo.horizontalPagination = .fit
    printInfo.verticalPagination = .fit
    printInfo.orientation = pageBounds.width > pageBounds.height ? .landscape : .portrait
    // 清除边距限制
    printInfo.topMargin = 0
    printInfo.bottomMargin = 0
    printInfo.leftMargin = 0
    printInfo.rightMargin = 0
    
    let printOperation = NSPrintOperation(view: pdfView, printInfo: printInfo)
    // 让打印视图的尺寸匹配纸张尺寸
    printOperation.view.frame = CGRect(x: 0, y: 0, width: printInfo.paperSize.width, height: printInfo.paperSize.height)
    printOperation.run()
}

关键修改说明

  • 直接使用PDFDocument的打印方法是最可靠的方式,系统内部会处理PDF页面与打印纸张的适配
  • 设置NSPrintInfo的边距为0,避免默认边距导致内容被截断
  • 若使用PDFView,必须开启autoScales并让视图尺寸匹配纸张尺寸,确保缩放逻辑生效

内容的提问来源于stack exchange,提问作者Trey6

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 19:23:07