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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:15:00