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

iOS Swift中UIView生成PDF后WebView显示空白问题咨询

iOS Swift中UIView生成PDF后WebView显示空白的问题排查与解决

问题描述

你在iOS Swift里把UIView生成PDF并保存为myforms文件,控制台显示PDF生成成功且文件存在,但在ViewController的WebView里只显示空白屏幕。你的生成和加载代码如下:

生成PDF的代码

@IBAction func createAct(_ sender: Any) {
    print("Creat PDF")
    self.createPdfFromView(mainView: mainView, saveToDocumentsWithFileName: "myforms")
}
func createPdfFromView(mainView: UIView, saveToDocumentsWithFileName fileName: String) {
    let pdfData = NSMutableData()
    UIGraphicsBeginPDFContextToData(pdfData, mainView.bounds, nil)
    UIGraphicsBeginPDFPage()
    guard let pdfContext = UIGraphicsGetCurrentContext() else { return }
    mainView.layer.render(in: pdfContext)
    UIGraphicsEndPDFContext()
    if let documentDirectories = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
        let documentsFileName = documentDirectories + "/" + fileName
        debugPrint(documentsFileName)
        pdfData.write(toFile: documentsFileName, atomically: true)
    }
}

PDFViewController加载PDF的代码

override func viewDidLoad() {
    super.viewDidLoad()
    let check = "myforms"
    var pdfURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
    print("check final = \(pdfURL)")
    pdfURL = pdfURL.appendingPathComponent(check) as URL
    if let pdfBundleURL = Bundle.main.url(forResource: "myforms", withExtension: nil, subdirectory: nil) {
        do {
            let data = try Data(contentsOf: pdfBundleURL)
            try data.write(to: pdfURL, options: .atomicWrite)
        } catch {
            // catch errors here
        }
    }
    do{
        let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        let url = URL(fileURLWithPath: path)
        var filePath = url.appendingPathComponent(check).path
        let fileManager1 = FileManager.default
        if fileManager1.fileExists(atPath: filePath) {
            print("FILE AVAILABLE in VC")
            filePath = "file://\(filePath)"
            let fileUrlkk = Foundation.URL(string: filePath)
            let data = try Data(contentsOf: fileUrlkk!)
            self.webView.load(data, mimeType: filePath, textEncodingName:"utf-8", baseURL: pdfURL.deletingLastPathComponent())
        } else {
            print("FILE NOT AVAILABLE in VC")
        }
    } catch let error as NSError {
        print("An error took place: \(error)")
    }
}

控制台确认文件存在,但WebView就是空白,我帮你排查出几个关键问题:


问题分析

  1. PDF文件无后缀名:你保存的文件名是myforms,没有.pdf后缀,WebView可能无法正确识别文件类型
  2. 坐标系统不匹配:UIKit的坐标原点在左上角,而Core Graphics(PDF上下文)的原点在左下角,直接渲染layer会导致内容被移出可视区域
  3. WebView加载参数错误:你把filePath作为mimeType传入,这完全错误,应该指定为application/pdf
  4. 冗余代码干扰:PDFViewController里试图从Bundle复制myforms文件到Documents,这会覆盖你之前生成的PDF(如果Bundle里有同名文件的话)

修复方案

1. 修正PDF生成代码

  • 给文件名加上.pdf后缀
  • 翻转PDF上下文以匹配UIKit的坐标系统
  • 确保正确渲染view的所有内容

修改后的createPdfFromView函数:

func createPdfFromView(mainView: UIView, saveToDocumentsWithFileName fileName: String) {
    // 加上.pdf后缀
    let fileNameWithExt = "\(fileName).pdf"
    let pdfData = NSMutableData()
    
    // 初始化PDF上下文,设置页面大小为view的bounds
    UIGraphicsBeginPDFContextToData(pdfData, mainView.bounds, nil)
    UIGraphicsBeginPDFPage()
    
    guard let pdfContext = UIGraphicsGetCurrentContext() else {
        UIGraphicsEndPDFContext()
        return
    }
    
    // 翻转上下文,匹配UIKit坐标系统
    pdfContext.translateBy(x: 0, y: mainView.bounds.size.height)
    pdfContext.scaleBy(x: 1.0, y: -1.0)
    
    // 渲染view的layer到上下文
    mainView.layer.render(in: pdfContext)
    
    UIGraphicsEndPDFContext()
    
    // 保存到Documents目录
    if let documentDirectories = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
        let documentsFileName = documentDirectories + "/" + fileNameWithExt
        debugPrint(documentsFileName)
        pdfData.write(toFile: documentsFileName, atomically: true)
    }
}

调用的时候保持不变,但文件名会自动加上后缀:

@IBAction func createAct(_ sender: Any) {
    print("Creat PDF")
    self.createPdfFromView(mainView: mainView, saveToDocumentsWithFileName: "myforms")
}

2. 简化并修正PDFViewController加载代码

  • 去掉冗余的Bundle复制逻辑
  • 直接用正确的URL加载PDF,指定正确的mimeType
  • 确保文件名带.pdf后缀

修改后的viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
    
    let fileName = "myforms.pdf"
    // 获取Documents目录下的PDF文件URL
    guard let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
        print("无法获取Documents目录")
        return
    }
    let pdfURL = documentsDir.appendingPathComponent(fileName)
    
    let fileManager = FileManager.default
    if fileManager.fileExists(atPath: pdfURL.path) {
        print("FILE AVAILABLE in VC")
        // 直接用URLRequest加载,更可靠
        let request = URLRequest(url: pdfURL)
        webView.load(request)
        
        // 或者如果你想用Data加载,修正mimeType:
        /*
        do {
            let data = try Data(contentsOf: pdfURL)
            webView.load(data, mimeType: "application/pdf", textEncodingName: "utf-8", baseURL: documentsDir)
        } catch {
            print("加载PDF数据失败:\(error)")
        }
        */
    } else {
        print("FILE NOT AVAILABLE in VC")
    }
}

验证步骤

  1. 运行APP,点击生成PDF的按钮
  2. 切换到PDFViewController,WebView应该能正确显示UIView生成的PDF内容了
  3. 你可以打开控制台打印的Documents目录路径,找到myforms.pdf文件,双击打开确认内容是否正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:03:58