Ios 在UITextview中点击word

Ios 在UITextview中点击word,ios,objective-c,swift,uitextview,uitapgesturerecognizer,Ios,Objective C,Swift,Uitextview,Uitapgesturerecognizer,我添加了一个最初不可编辑的uitextview。我添加了一个轻触手势,使编辑变为真。在点击手势选择器中,我得到被点击的单词。我尝试了很多解决方案,但没有一个能作为一个完整的解决方案对我有效。如果文本视图没有滚动,每个解决方案都有效。但如果我滚动文本视图,则无法检索到确切的单词。以下是我获取被点击单词的代码: @objc func handleTap(_ sender: UITapGestureRecognizer) { notesTextView.isEditable = true

我添加了一个最初不可编辑的uitextview。我添加了一个轻触手势,使编辑变为真。在点击手势选择器中,我得到被点击的单词。我尝试了很多解决方案,但没有一个能作为一个完整的解决方案对我有效。如果文本视图没有滚动,每个解决方案都有效。但如果我滚动文本视图,则无法检索到确切的单词。以下是我获取被点击单词的代码:

 @objc func handleTap(_ sender: UITapGestureRecognizer) {

    notesTextView.isEditable = true
    notesTextView.textColor = UIColor.white

    if let textView = sender.view as? UITextView {

        var pointOfTap = sender.location(in: textView)
        print("x:\(pointOfTap.x) , y:\(pointOfTap.y)")

        let contentOffsetY = textView.contentOffset.y
        pointOfTap.y += contentOffsetY
        print("x:\(pointOfTap.x) , y:\(pointOfTap.y)")
        word(atPosition: pointOfTap)

 }

func word(atPosition: CGPoint) -> String? {
    if let tapPosition = notesTextView.closestPosition(to: atPosition) {
        if let textRange = notesTextView.tokenizer.rangeEnclosingPosition(tapPosition , with: .word, inDirection: 1) {
            let tappedWord = notesTextView.text(in: textRange)
            print("Word: \(tappedWord)" ?? "")
            return tappedWord
        }
        return nil
    }
    return nil
}
编辑: 下面是有问题的演示项目。
您不需要添加文本视图的内容偏移量。当您将位置转换为滚动视图时,它已经将其内容偏移量考虑在内

删除:

let contentOffsetY = textView.contentOffset.y
pointOfTap.y += contentOffsetY
应该可以。请试试这个

//add UITextViewDelegate 

    let termsAndConditionsURL = "someText"
        let privacyURL = "SampleText"

        @IBOutlet weak var terms: UITextView!

     override func viewDidLoad() {
            super.viewDidLoad()

            self.terms.delegate = self

    // Adding Attributed text to TextView

            let str = "By registering, you agree to the Terms and the User Privacy Statement."
            let attributedString = NSMutableAttributedString(string: str)
            var foundRange = attributedString.mutableString.range(of: "Terms")
            attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue, range: foundRange)
            attributedString.addAttribute(NSAttributedStringKey.underlineStyle , value: NSUnderlineStyle.styleSingle.rawValue, range: foundRange)
            attributedString.addAttribute(NSAttributedStringKey.link, value: termsAndConditionsURL, range: foundRange)
            foundRange = attributedString.mutableString.range(of: "User Privacy Statement")
            attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue, range: foundRange)
            attributedString.addAttribute(NSAttributedStringKey.underlineStyle , value: NSUnderlineStyle.styleSingle.rawValue, range: foundRange)
            attributedString.addAttribute(NSAttributedStringKey.link, value: privacyURL, range: foundRange)
            terms.attributedText = attributedString
            // Do any additional setup after loading the view.
        }


     func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool
        {
            if (URL.absoluteString == termsAndConditionsURL)
            {
    // Perform Terms Action here
            } else if (URL.absoluteString == privacyURL)
            {
    // Perform Terms Action here

            }
            return false
        }

Swift 4中最好最简单的方法

方法1:

步骤1:在文本视图上添加点击手势

let tap = UITapGestureRecognizer(target: self, action: #selector(tapResponse(recognizer:)))

textViewTC.addGestureRecognizer(tap)
步骤2:执行轻触手势

@objc func tapResponse(recognizer: UITapGestureRecognizer) {
        let location: CGPoint = recognizer.location(in: textViewTC)
        let position: CGPoint = CGPoint(x: location.x, y: location.y)
        let tapPosition: UITextPosition = textViewTC.closestPosition(to: position)!
        guard let textRange: UITextRange = textViewTC.tokenizer.rangeEnclosingPosition(tapPosition, with: UITextGranularity.word, inDirection: 1) else {return}

        let tappedWord: String = textViewTC.text(in: textRange) ?? ""
        print("tapped word ->", tappedWord)
    }
是的,就是这样。去做吧

方法2:

另一种方法是,您可以为textview启用链接,然后将其设置为属性。这里有一个例子

var foundRange = attributedString.mutableString.range(of: "Terms of Use") //mention the parts of the attributed text you want to tap and get an custom action
attributedString.addAttribute(NSAttributedStringKey.link, value: termsAndConditionsURL, range: foundRange)
将此属性text设置为Textview和
Textview.delegate=self

现在您只需要在

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {

希望对你有帮助。祝你一切顺利。

库纳尔·古普塔的方法1对我很有效。 在两个函数中运行代码根本不起作用,这可能是错误。 我报告了一个关于这种情况的问题

我对上述代码进行了回购:


这两个位置通过以下方法返回:recognizer.location(in:notesTextView)不一样,可能是notesTextView或recognizer中发生了一些事情。

我认为
textView.contentOffset.y
应该是
textView.scrollView.contentOffset.y
试试看……不,这不会解决问题。实际上,当文本之间有空行时,问题就出现了。我的意思是当有下一行字符时。你说如果不滚动它就可以工作,只知道是否有空行?你能相应地编辑这个问题吗?样本项目将非常有帮助,我删除了它。直到文本中没有新行为止。如果文本中有新行,则在将文本视图滚动到下面一点后,该词不准确。我不确定新行是什么意思。我使用的代码如下:我添加了一行空行文本,但它似乎仍然有效,也许你可以看到有什么不同。一般来说,我认为word代表相当小的触摸目标,所以如果你没有得到确切的word,但我会说问题在于界面而不是代码。是的,你是对的。我说的是你添加的空行。不同的是你在一个操场上尝试。在带有文本视图的实际viewcontroller中尝试。滚动文本视图并点击最后一段中的任何单词。这个词不是被点击的词。我已经添加了一个带有这个问题的演示项目。你能帮我一下吗?我的代码已经正确了。如果我在新项目或新控制器中使用它,它会工作得很好。但它不适用于现有项目,因为约束可能存在一些问题。我已附上上述代码。如果你能检查一下并找出问题所在,我会很高兴的。