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

macOS Swift将HTML转PDF遇PMSessionBeginCGDocumentNoDialog() -61错误求助

Swift将HTML转为PDF时PMSessionBeginCGDocumentNoDialog()返回-61错误的修复方案

嘿,作为Swift新手想用HTML生成PDF发票却碰到这个问题,确实挺闹心的!我帮你梳理下问题根源,再给你调整后的可用代码:

问题根源分析

你碰到的-61错误虽然提示权限,但核心问题其实不是沙箱——你的代码里只给了保存目录,没指定具体的PDF文件名,系统根本不知道要把文件存成啥,自然写入失败;另外用NSTextField承载HTML富文本,也容易出现渲染不全或打印会话的额外问题;至于-1002错误,大概率是HTML里引用了外部网络资源(比如图片、样式)加载失败导致的,先解决PDF写入的核心问题再说。

修复后的代码

func makePDF(markup: String) {
    // 1. 生成带时间戳的唯一PDF文件名,避免覆盖
    let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let pdfFileURL = documentsDir.appendingPathComponent("invoice_\(Date().timeIntervalSince1970).pdf")
    
    // 2. 配置打印信息,明确纸张尺寸和保存路径
    let printOpts: [NSPrintInfo.AttributeKey: Any] = [
        .jobDisposition: NSPrintInfo.JobDisposition.save,
        .jobSavingURL: pdfFileURL,
        .paperSize: NSPaperSize.A4
    ]
    let printInfo = NSPrintInfo(dictionary: printOpts)
    printInfo.topMargin = 20.0
    printInfo.leftMargin = 20.0
    printInfo.rightMargin = 20.0
    printInfo.bottomMargin = 20.0
    
    guard let htmlData = markup.data(using: .utf8) else {
        print("无法将HTML转为UTF8格式数据")
        return
    }
    
    // 3. 直接用PDFKit渲染富文本,绕开NSPrintOperation的坑
    do {
        let attrStr = try NSAttributedString(
            data: htmlData,
            options: [
                .documentType: NSAttributedString.DocumentType.html,
                .characterEncoding: String.Encoding.utf8.rawValue
            ],
            documentAttributes: nil
        )
        
        // 设置PDF页面尺寸和可打印区域
        let pageSize = printInfo.paperSize
        let pageRect = NSRect(x: 0, y: 0, width: pageSize.width, height: pageSize.height)
        let printableRect = printInfo.printableRect
        
        // 生成PDF数据
        let pdfData = NSMutableData()
        UIGraphicsBeginPDFContextToData(pdfData, pageRect, nil)
        
        let textRange = NSRange(location: 0, length: attrStr.length)
        attrStr.draw(with: printableRect, options: .usesLineFragmentOrigin, range: textRange, context: nil)
        
        UIGraphicsEndPDFContext()
        
        // 写入到指定文件
        do {
            try pdfData.write(to: pdfFileURL)
            print("PDF生成成功!路径:\(pdfFileURL.path)")
        } catch {
            print("写入PDF文件失败:\(error.localizedDescription)")
        }
        
    } catch {
        print("HTML转富文本失败:\(error.localizedDescription)")
    }
}

关键改动说明

  • 指定完整文件名:原来只传了目录URL,现在生成带时间戳的唯一文件名,让系统明确写入目标
  • 改用PDFKit直接渲染:放弃NSTextField + NSPrintOperation的方式,直接用PDF上下文渲染富文本,避免打印会话的权限和渲染bug
  • 明确纸张尺寸:添加A4纸张配置,适配标准发票的排版需求
  • 完善错误处理:添加guard和do-catch,方便你排查每一步的问题

额外建议

  • 关于-1002错误:检查你的HTML里是否有外部网络资源(比如<img>标签的网络链接),如果有,记得在Info.plist里配置NSAppTransportSecurity允许HTTP资源,或者改用HTTPS链接
  • 权限验证:如果还是碰到权限问题,可以打印pdfFileURL.path,手动去这个目录看看能不能创建文件,确认目录的读写权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:37:01