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就是空白,我帮你排查出几个关键问题:
问题分析
- PDF文件无后缀名:你保存的文件名是
myforms,没有.pdf后缀,WebView可能无法正确识别文件类型 - 坐标系统不匹配:UIKit的坐标原点在左上角,而Core Graphics(PDF上下文)的原点在左下角,直接渲染layer会导致内容被移出可视区域
- WebView加载参数错误:你把
filePath作为mimeType传入,这完全错误,应该指定为application/pdf - 冗余代码干扰: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") } }
验证步骤
- 运行APP,点击生成PDF的按钮
- 切换到PDFViewController,WebView应该能正确显示UIView生成的PDF内容了
- 你可以打开控制台打印的Documents目录路径,找到
myforms.pdf文件,双击打开确认内容是否正确
内容的提问来源于stack exchange,提问作者iOS Developer
相关产品推荐
相关产品推荐

