【问题标题】:Removing highlight annotation with PDFKit使用 PDFKit 删除高亮注释
【发布时间】:2026-02-18 21:55:01
【问题描述】:

我正在使用 swift 和 PDFKit 成功地将高亮注释添加到 pdf,但我无法弄清楚如何让用户再次删除高亮。

用户可以正常选择文本,然后从 UIMenu 中选择“突出显示”或“取消突出显示”。

为了在选择文本时自定义 pdfView,我更改了出现的菜单 - 首先删除默认操作:

extension PDFView {
    override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return false
    }
}

然后在 viewDidLoad() 中我设置了我的自定义 UIMenuItems:

let menuItem1 = UIMenuItem(title: "Highlight", action: #selector(highlightSelection(_:)))        
let menuItem2 = UIMenuItem(title: "Remove highlight", action: #selector(removeHighlightSelection(_:)))
UIMenuController.shared.menuItems = [menuItem1, menuItem2]

选择高亮时:

@objc func highlightSelection(_ sender: UIMenuItem) {
            let selections = pdfViewer.currentSelection?.selectionsByLine()
            guard let page = selections?.first?.pages.first else { return }

            selections?.forEach({ selection in
                let highlight = PDFAnnotation(bounds: selection.bounds(for: page), forType: .highlight, withProperties: nil)
                highlight.color = .yellow
                page.addAnnotation(highlight)
            })
    }

到目前为止,一切都很好 - 到目前为止一切正常。突出显示文本并创建注释。

现在是我的问题:

当我选择突出显示的文本时,我希望用户能够通过点击“删除突出显示”来删除突出显示注释,但我根本无法弄清楚如何仅删除隐藏在所选文本“后面”的注释。

此代码有效,但删除了整个页面上的所有注释:

@objc func removeHighlightSelection(_ sender: UIMenuItem) {
        let selections = pdfViewer.currentSelection?.selectionsByLine()
        guard let page = selections?.first?.pages.first else { return }

        let annotationsToRemove = page.annotations

        for annotation in annotationsToRemove {
            page.removeAnnotation(annotation)
            print("Removed: \(annotation)")
        }
    }

那么,如何仅删除选定的高亮注释?

顺便说一句 - 我知道整个菜单的东西并不真正相关,但我希望有人在使用高亮注释时会发现这个问题,然后能够使用该部分。

谢谢, 埃米尔。

【问题讨论】:

    标签: swift pdf annotations highlight pdfkit


    【解决方案1】:

    在此处查看此通知:PDFViewAnnotationHitNotification:https://developer.apple.com/documentation/foundation/nsnotification/name/1504809-pdfviewannotationhit

    向通知监听器添加一个目标

    当注释被按下时,从 userInfo 中返回“PDFAnnotationHit”的 PDFViewAnnotationHitNotification 的字典值,您将获得所按下的确切注释,一旦您拥有此注释,请将其删除。

    【讨论】:

    • 感谢您的帮助。我能够将您的答案用于我遇到的另一个问题,但最终我以另一种方式解决了这个问题。我已经发布了我的解决方案作为答案。
    【解决方案2】:

    好吧,其实过了一会儿我就想通了。

    我决定采用以下方法来删除高亮注释:

    1:获取页面上的所有注释。

    2:检测哪些注解是当前选择的一部分通过检查注解的 bounds.origin 是否在选择范围内。

    3:检查所选注释是否属于“突出显示”类型并仅删除这些。

    4:删除注释。

    5:不要忘记在某个时候保存更改。

    //Remove highlight annotations that are part of the current selection.
    @objc func removeHighlightSelection(_ sender: UIMenuItem) {
        let selection = PDFSelection.init(document: pdfViewer.document!)
        selection.add(pdfViewer.currentSelection!)
        let selectionBounds = selection.bounds(for: pdfViewer.currentPage!)
        let annotations = pdfViewer.currentPage?.annotations
        let annotationsToDelete = NSMutableArray()
    
        for annotation in annotations! {
            let annotationPoint = annotation.bounds.origin
            if selectionBounds.contains(annotationPoint) {
                annotationsToDelete.add(annotation)
                print(annotationsToDelete)
            }
        }
    
        for annotation in annotationsToDelete {
            let onlyHighlight = annotation as! PDFAnnotation
            if onlyHighlight.type == "Highlight" {
                pdfViewer.currentPage?.removeAnnotation(onlyHighlight)
                print("Removed highlight annotation: \(onlyHighlight)")
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果您使用 UISearchBar 突出显示文本,请使用这些方法

      1- 删除旧注释

        func removeAllAnnotations() {
          guard let document = self.baseView.document else { return }
      
          for i in 0..<document.pageCount {
              if let page = document.page(at: i) {
                  let annotations = page.annotations
                  for annotation in annotations {
                      page.removeAnnotation(annotation)
                  }
              }
          }
      }
      

      2-添加新注释

      func highlight(searchTerms: [String]?)
      {
         searchTerms?.forEach { term in
            let selections = baseView?.document?.findString(term, withOptions: [.caseInsensitive])
            selections?.forEach { selection in
      
              for page in selection.pages{
                  let highlight = PDFAnnotation(bounds: selection.bounds(for: page), forType: .highlight, withProperties: nil)
                 highlight.endLineStyle = .square
                 highlight.color = UIColor.orange.withAlphaComponent(0.5)
                 highlightsAnotation.append(highlight)
                 page.addAnnotation(highlight)
              }
            }
         }
      }
      

      在 UISearchBarDelegates 中调用这些方法

       func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
          removeAllAnnotations()
          highlight(searchTerms: [searchText])
      }
      

      【讨论】: