如何实现在WKWebView加载的PDF文件中查找并高亮指定字符串?
WKWebView加载PDF时页面内查找功能失效的解决方法
问题原因
WKWebView加载PDF时,底层依赖PDFKit渲染而非WebKit的DOM环境,导致:
find(_:configuration:completionHandler:)原生方法对PDF内容无作用- 原代码中依赖的
window.getSelection()等JavaScript API无法执行,无法完成滚动和高亮逻辑
解决方案
需要针对PDF内容单独处理,直接使用PDFKit的搜索API实现页面内查找功能,步骤如下:
- 区分内容类型:调用查找方法前,先判断当前WKWebView加载的是HTML还是PDF
- PDF场景下的搜索实现:
- 获取对应
PDFDocument实例 - 用PDFKit的API查找匹配内容
- 定位到匹配的页面并滚动到对应位置
- 高亮匹配内容
- 获取对应
代码示例
修改原searchInPage方法,增加PDF处理分支:
import PDFKit private func searchInPage(forward: Bool) { ktWebView.select(nil) searchIsAtTop = false searchIsAtEnd = false // 判断当前内容是否为PDF guard let url = ktWebView.url, url.pathExtension.lowercased() == "pdf", let pdfDocument = PDFDocument(url: url) else { // HTML场景沿用原逻辑 let searchConfig = WKFindConfiguration() searchConfig.backwards = !forward searchConfig.caseSensitive = false searchConfig.wraps = false ktWebView.find(searchString, configuration: searchConfig, completionHandler: { result in guard result.matchFound else { if forward { searchIsAtEnd = true } else { searchIsAtTop = true } return } ktWebView.evaluateJavaScript("window.getSelection().getRangeAt(0).getBoundingClientRect().top") { offset, _ in guard let offset = offset as? CGFloat else { return } ktWebView.scrollView.scrollRectToVisible( .init(x: 0, y: offset + ktWebView.scrollView.contentOffset.y, width: 100, height: 100), animated: true) } }) return } // PDF场景处理逻辑 let options: NSString.CompareOptions = [.caseInsensitive] let currentPageIndex = ktWebView.scrollView.contentOffset.y / ktWebView.scrollView.contentSize.height * CGFloat(pdfDocument.pageCount) // 获取初始匹配项 guard let baseSelection = pdfDocument.findString(searchString, withOptions: options) else { if forward { searchIsAtEnd = true } else { searchIsAtTop = true } return } // 根据查找方向获取目标匹配项 let targetSelection: PDFSelection? = forward ? baseSelection.findNextMatch() : baseSelection.findPreviousMatch() guard let target = targetSelection else { if forward { searchIsAtEnd = true } else { searchIsAtTop = true } return } // 滚动到匹配位置 guard let targetPage = target.pages.first else { return } let pageHeightRatio = CGFloat(targetPage.index) / CGFloat(pdfDocument.pageCount) let scrollBaseY = pageHeightRatio * ktWebView.scrollView.contentSize.height let matchRect = target.bounds(for: targetPage) let absoluteY = scrollBaseY + matchRect.origin.y ktWebView.scrollView.scrollRectToVisible( CGRect(x: 0, y: absoluteY, width: 100, height: 100), animated: true) // 高亮匹配内容 target.color = UIColor.yellow.withAlphaComponent(0.5) if let pdfView = ktWebView.subviews.first(where: { $0 is PDFView }) as? PDFView { pdfView.setSelections([target], animate: true) } }
注意事项
- 如果PDF是通过
load(_:mimeType:characterEncodingName:baseURL:)加载的,需保留PDF数据并直接初始化PDFDocument,而非通过URL获取 - WKWebView中的PDFView为私有子视图,若兼容性要求高,建议直接使用
PDFView替代WKWebView显示PDF,搜索逻辑会更易维护 - 高亮效果可根据需求调整颜色和透明度,确保在PDF内容中清晰可见
内容的提问来源于stack exchange,提问作者Clemens
相关产品推荐
相关产品推荐

