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

Swift+PDFKit实现iOS PDF单词点击发音的代码修改求助

Hey there! Let's get that word-click-to-speak feature up and running for your iOS PDF reader. You're already halfway there with the PDF display and speech synthesis—we just need to bridge the gap between tapping a word and triggering the audio. Here's how to modify your ViewController.swift:

Step-by-Step Explanation & Modified Code

First, we'll add a tap gesture recognizer to catch user taps on the PDFView. Then we'll convert the tap's screen coordinates to PDF page coordinates, grab the tapped word, and pass it to your speech synthesizer.

import UIKit
import PDFKit
import AVFoundation

class ViewController: UIViewController {
    @IBOutlet weak var pdfView: PDFView!
    // Make the speech synthesizer a class property to avoid recreating it on every tap
    private let speechSynth = AVSpeechSynthesizer()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Load your PDF document as before
        if let url = Bundle.main.url(forResource: "pdf", withExtension: "pdf"),
           let pdfDocument = PDFDocument(url: url) {
            pdfView.autoScales = true
            pdfView.document = pdfDocument
            // Tell the PDFView we want to select text by whole words
            pdfView.selectionMode = .byWord
        }
        
        // Add a tap gesture recognizer to handle word taps
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handlePDFTap(_:)))
        pdfView.addGestureRecognizer(tapGesture)
    }
    
    @objc private func handlePDFTap(_ gesture: UITapGestureRecognizer) {
        // Get the tap location on the screen
        let tapPoint = gesture.location(in: pdfView)
        
        // Convert the screen point to a point within the PDF page
        guard let tappedPage = pdfView.page(for: tapPoint, nearest: true),
              let pageBounds = tappedPage.bounds(for: pdfView.displayBox) else {
            return // Exit if we can't find the tapped page
        }
        let pdfCoordinatePoint = pdfView.convert(tapPoint, to: tappedPage, for: pageBounds)
        
        // Grab the word at the tapped coordinate
        // The `within` parameter creates a small "hit box" to account for slight tap inaccuracies
        guard let wordSelection = tappedPage.selection(for: pdfCoordinatePoint, at: .word, within: CGSize(width: 10, height: 10)) else {
            return // Exit if no word was found at the tap location
        }
        
        // Extract the text of the selected word
        guard let wordToSpeak = wordSelection.string else {
            return
        }
        
        // Trigger speech synthesis for the word
        let utterance = AVSpeechUtterance(string: wordToSpeak)
        utterance.voice = AVSpeechSynthesisVoice(language: "en-US")
        speechSynth.speak(utterance)
    }
}

Key Details to Note

  • Speech Synthesizer as Class Property: We moved speechSynth to a class-level variable so we don't create a new synthesizer instance every time the user taps a word—this is more efficient.
  • PDF Selection Mode: Setting pdfView.selectionMode = .byWord ensures the PDFView prioritizes selecting entire words when tapped.
  • Coordinate Conversion: Screen coordinates don't directly map to PDF page coordinates, so we use convert(_:to:for:) to translate the tap position correctly.
  • Hit Box Adjustment: The within: CGSize(width: 10, height: 10) parameter lets users tap slightly off-center of a word and still have it recognized. You can adjust this size if needed (bigger = more forgiving taps).

Important Caveat

This works only with text-based PDFs—scanned PDFs (which are just images) won't have selectable text, so you won't be able to extract words from them.

内容的提问来源于stack exchange,提问作者user8460166

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 12:57:36