PDFKit PDFView选中文本菜单自定义及高亮失效问题问询
PDFKit文本选中菜单问题解决:修复高亮无响应+自定义菜单
问题
使用PDFKit开发时,长按选中PDF文本弹出的系统菜单中,点击「高亮」选项无响应;同时需要替换系统默认的高亮、复制等选项为自定义菜单。
现有代码
class MyPDFVC: UIViewController, PDFViewDelegate { let pdfView = PDFView() override func viewDidLoad() { super.viewDidLoad() pdfView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height) pdfView.isUserInteractionEnabled = true pdfView.delegate = self self.view.addSubview(pdfView) //加载的 PDF 文件 if let pdfURL = Bundle.main.url(forResource: "SPR-pdf", withExtension: "pdf"), let pdfDocument = PDFDocument(url: pdfURL) { pdfView.document = pdfDocument pdfView.goToFirstPage(nil) } } }
解决方案
1. 修复系统高亮无响应
系统高亮失效核心原因是未开启文档编辑权限和PDFView的可编辑属性,在加载文档时添加以下配置:
pdfDocument?.allowsEditing = true pdfView.isEditable = true
2. 自定义文本选择菜单
要替换系统默认菜单,需通过自定义PDFView子类,拦截系统动作并构建自定义菜单:
步骤1:创建CustomPDFView子类
class CustomPDFView: PDFView { // 存储当前选中的文本范围 private var currentSelection: PDFSelection? // 屏蔽系统默认的高亮、复制选项 override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { if action == #selector(highlight(_:)) || action == #selector(copy(_:)) { return false } // 允许自定义菜单选项触发 if action == #selector(customHighlight(_:)) || action == #selector(customCopy(_:)) { return currentSelection != nil } return super.canPerformAction(action, withSender: sender) } // 构建自定义菜单 override func buildMenu(with builder: UIMenuBuilder) { super.buildMenu(with: builder) // 移除系统默认编辑菜单 builder.remove(menu: .edit) // 创建自定义菜单项 let highlightAction = UIAction(title: "自定义高亮", image: UIImage(systemName: "highlighter")) { [weak self] _ in self?.customHighlight(nil) } let copyAction = UIAction(title: "自定义复制", image: UIImage(systemName: "doc.on.doc")) { [weak self] _ in self?.customCopy(nil) } // 添加自定义菜单组 let customEditMenu = UIMenu(title: "", children: [highlightAction, copyAction]) builder.insertChild(customEditMenu, atStartOfMenu: .edit) } // 监听选中状态变化,保存选中范围 override func selectionChanged(_ notification: Notification) { super.selectionChanged(notification) currentSelection = self.currentSelection } // 自定义高亮实现 @objc private func customHighlight(_ sender: Any?) { guard let selection = currentSelection, let page = currentPage else { return } // 创建高亮注解 let highlightAnnotation = PDFAnnotation( bounds: selection.bounds(for: page), forType: .highlight, withProperties: nil ) highlightAnnotation.color = UIColor.yellow.withAlphaComponent(0.3) // 添加到PDF页面 page.addAnnotation(highlightAnnotation) // 清除选中状态 clearSelection() } // 自定义复制实现 @objc private func customCopy(_ sender: Any?) { guard let selection = currentSelection else { return } UIPasteboard.general.string = selection.string clearSelection() } }
步骤2:在ViewController中替换为自定义PDFView
修改原代码中的PDFView实例为CustomPDFView,并补全编辑权限配置:
class MyPDFVC: UIViewController { // 使用自定义PDFView let pdfView = CustomPDFView() override func viewDidLoad() { super.viewDidLoad() // 适配屏幕尺寸与旋转 pdfView.frame = view.bounds pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight] pdfView.isUserInteractionEnabled = true pdfView.isEditable = true view.addSubview(pdfView) // 加载PDF文档 if let pdfURL = Bundle.main.url(forResource: "SPR-pdf", withExtension: "pdf"), let pdfDocument = PDFDocument(url: pdfURL) { pdfDocument.allowsEditing = true pdfView.document = pdfDocument pdfView.goToFirstPage(nil) } } }
核心说明
- 开启
allowsEditing和isEditable是系统高亮功能生效的必要条件,自定义高亮则可完全独立实现,无需依赖系统逻辑 - 通过
buildMenu(with:)可以完全重构菜单结构,灵活添加或移除菜单项 - 监听
selectionChanged事件能实时获取文本选中范围,为自定义操作提供数据支撑
内容的提问来源于stack exchange,提问作者blueblue
相关产品推荐
相关产品推荐

