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

macOS多页打印异常:仅第一页触发draw方法

macOS多页打印仅第一页有内容问题排查

我正在为macOS应用实现打印功能,已按照Apple开发者文档创建自定义NSView类处理打印,遵循《Laying Out Page Content》文档指导实现多页打印。

PrintView类代码

import Cocoa

class PrintView: NSView {
    let configuration: PrintConfiguration // 包含边距信息及工具方法的结构体
    let info = NSPrintInfo.shared
    private(set) var pageNum = 0
    
    private(set) var ranges: [NSRange] = [] // 预计算的每页内容范围数组
    private(set) var content: NSAttributedString 

    override var isFlipped: Bool {
        return true
    }
    
    init(printContent: NSAttributedString, config: PrintConfiguration, ranges: [NSRange]) {
        self.content = printContent
        self.ranges = ranges
        self.configuration = config
        super.init(frame: CGRect(origin: .zero, size: info.paperSize))
        self.frame.size.height = config.printHeight
        info.verticalPagination = .automatic
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    override func draw(_ dirtyRect: NSRect) {
        print("Entering draw - dirtyRect: \(dirtyRect)")
        
        let rangeNum = pageNum - 1 // 转换为0索引访问数组
        let range = ranges[rangeNum]
        let text = self.content.attributedSubstring(from: range)
        let drawRect = configuration.printRect
        text.draw(in: drawRect)
    }
    
    override func knowsPageRange(_ range: NSRangePointer) -> Bool {
        print("Entering knowsPageRange")
        range.pointee.location = 1
        range.pointee.length = self.ranges.count
        
        print("Page range: \(range.pointee)")
        return true
    }
    
    override func rectForPage(_ page: Int) -> NSRect {
        print("Entering rectForPage")
        self.pageNum = page
        let pageHeight = configuration.printHeight
        let pageNum = CGFloat(page - 1)
        let printRect = CGRect(x: configuration.leftMargin,
                               y: (pageNum * pageHeight) + configuration.topMargin,
                               width: configuration.printWidth,
                               height: configuration.printHeight)
        print("Print rect: \(printRect)")
        return printRect
    }
    
    override func locationOfPrintRect(_ rect: NSRect) -> NSPoint { // 仅用于调试是否被调用,非实现必需
        print("Entering locationOfPrintRect")
        return NSPoint(x: self.configuration.leftMargin, y: self.configuration.topMargin)
    }
}

打印调用代码

let printView = PrintView(printContent: text, config: printConfiguration, ranges: ranges)

let info = NSPrintInfo.shared

let printOp = NSPrintOperation(view: printView, printInfo: info)
printOp.jobTitle = title // 视图属性
printOp.canSpawnSeparateThread = true
printOp.run()

控制台输出情况

两页文本场景

Entering knowsPageRange
Page range: {1, 2}
Entering knowsPageRange
Page range: {1, 2}
Entering rectForPage
Print rect: (40.0, 80.0, 532.0, 652.0)
Entering locationOfPrintRect
Entering draw - dirtyRect: (40.0, 80.0, 532.0, 572.0)
Entering rectForPage
Print rect: (40.0, 732.0, 532.0, 652.0)
Entering locationOfPrintRect

六页文本场景

Entering knowsPageRange
Page range: {1, 6}
Entering knowsPageRange
Page range: {1, 6}
Entering rectForPage
Print rect: (40.0, 80.0, 532.0, 652.0)
Entering locationOfPrintRect
Entering draw - dirtyRect: (40.0, 80.0, 532.0, 572.0)
Entering rectForPage
Print rect: (40.0, 732.0, 532.0, 652.0)
Entering locationOfPrintRect
Entering rectForPage
Print rect: (40.0, 1384.0, 532.0, 652.0)
Entering locationOfPrintRect

问题现象

  • 打印预览对话框显示正确页数,但仅第一页有内容,后续页面空白
  • 实际打印到Preview应用也仅显示第一页文本
  • 除draw方法外,其他分页相关方法调用次数符合预期(或更多),但draw仅被调用一次

希望有人指出问题所在。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:57:03