iOS Swift 5下如何将Office文档转为PDF并获取多格式文档页数
iOS Swift5 下获取Office文档页数的实现方案
核心思路
你之前通过WebKit的WebView直接提取页数返回0,是因为WebKit没有对外暴露直接读取Office文档分页的官方接口,内部渲染的分页信息无法直接获取。通过「WebView加载文档→原生渲染转PDF→读取PDF页数」的路径是目前无需引入第三方SDK的最稳定实现方案,兼容doc、docx、ppt、pptx、xls、xlsx所有主流Office格式。
完整实现代码
需要导入三个原生框架:WebKit、PDFKit、UIKit
import UIKit import WebKit import PDFKit class OfficePageCounter: NSObject, WKNavigationDelegate { private var webView: WKWebView! private var completion: ((Int) -> Void)? override init() { super.init() let config = WKWebViewConfiguration() webView = WKWebView(frame: .zero, configuration: config) webView.navigationDelegate = self } /// 获取Office文档页数 /// - Parameters: /// - fileURL: 本地Office文件的沙盒URL /// - completion: 回调返回页数,加载失败返回0 func getPageCount(for fileURL: URL, completion: @escaping (Int) -> Void) { self.completion = completion let request = URLRequest(url: fileURL) webView.load(request) } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // 延迟等待复杂文档渲染完成,可根据实际场景调整延迟时长 DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in guard let self = self else { return } let renderer = UIPrintPageRenderer() renderer.addPrintFormatter(webView.viewPrintFormatter(), startingAtPageAt: 0) // 定义A4纸标准尺寸,和Office默认分页规则对齐 let a4PageRect = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) renderer.setValue(NSValue(cgRect: a4PageRect), forKey: "paperRect") renderer.setValue(NSValue(cgRect: a4PageRect), forKey: "printableRect") // 生成PDF数据 let pdfData = NSMutableData() UIGraphicsBeginPDFContextToData(pdfData, a4PageRect, nil) renderer.prepare(forDrawingPages: NSRange(location: 0, length: renderer.numberOfPages)) for pageIndex in 0..<renderer.numberOfPages { UIGraphicsBeginPDFPage() renderer.drawPage(at: pageIndex, in: UIGraphicsGetPDFContextBounds()) } UIGraphicsEndPDFContext() // 读取PDF页数 if let pdfDocument = PDFDocument(data: pdfData as Data) { self.completion?(pdfDocument.pageCount) } else { self.completion?(0) } } } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { completion?(0) } }
使用方法
- 首先将目标Office文档下载到本地沙盒,获取本地文件URL(不支持直接加载远程URL)
- 需要在调用处持有
OfficePageCounter实例,避免异步回调过程中实例被提前释放,调用示例:
// 全局持有counter,避免提前释放 var pageCounterHolder: OfficePageCounter? // 示例调用 if let localFileUrl = Bundle.main.url(forResource: "test", withExtension: "docx") { pageCounterHolder = OfficePageCounter() pageCounterHolder?.getPageCount(for: localFileUrl) { pageCount in print("文档页数为:\(pageCount)") // 用完可释放实例 self.pageCounterHolder = nil } }
注意事项
- 支持iOS 11及以上系统版本
- xls/xlsx类表格文档的分页规则和PC端Office的A4纸分页结果基本一致
- 超大体积的Office文档可自行添加加载超时判断,避免长时间无回调
- 如果不需要留存PDF文件,生成的PDF数据仅用于读取页数,不会占用额外的磁盘存储空间
内容的提问来源于stack exchange,提问作者Heyman
相关产品推荐
相关产品推荐

