ios 如何在UITextView中高效地查找可见词的CGRect?

kpbwa7wx  于 2023-02-01  发布在  iOS
关注(0)|答案(2)|浏览(141)

我的目标是在UITextView中标记所有可见的拼写错误的单词。
低效的算法是使用拼写检查器找到文本中所有拼写错误的单词范围,使用positionFromPosition:inDirection:offset等将它们转换为UITextRange对象,然后使用UITextInput方法firstRectFromRange获得图形矩形。
因此,所有文本-〉拼写错误的单词-〉NSRange集合-〉UITextRange集合-〉CGRect集合-〉评估可见性,绘制可见的单词
问题是,这需要检查所有的文本,并将所有拼写错误的单词转换为图形rect。
因此,我认为要做的事情是找出UITextView中的底层. text的哪些部分是当前可见的。
因此,对于可见文本范围-〉拼写错误的单词-〉NSRange集合-〉UITextRange集合-〉CGRect集合-〉评估可见性,绘制可见的文本
ios - how to find what is the visible range of text in UITextView?中的代码可以作为一种方式来约束要检查的文本部分,但仍然需要测量所有文本,我想这可能会相当昂贵。
有什么建议吗?

hsvhsicv

hsvhsicv1#

因为UITextViewUIScrollView的子类,它的bounds属性反映了坐标系的可见部分,所以应该可以这样做:

- (NSRange)visibleRangeOfTextView:(UITextView *)textView {
    CGRect bounds = textView.bounds;
    UITextPosition *start = [textView characterRangeAtPoint:bounds.origin].start;
    UITextPosition *end = [textView characterRangeAtPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))].end;
    return NSMakeRange([textView offsetFromPosition:textView.beginningOfDocument toPosition:start],
        [textView offsetFromPosition:start toPosition:end]);
}

这假设了一个从上到下,从左到右的文本布局。如果你想让它适用于其他布局方向,你将不得不更加努力。:)

7kjnsjlb

7kjnsjlb2#

Rob的答案,写在Swift 4中。我添加了一些安全检查。

private func visibleRangeOfTextView(textView: UITextView) -> NSRange {
    let bounds = textView.bounds
    let origin = CGPoint(x: 10, y: 10)
    guard let startCharacterRange = textView.characterRange(at: origin) else {
        return NSRange(location: 0, length: 0)
    }
    
    let startPosition = startCharacterRange.start
    let endPoint = CGPoint(x: bounds.maxX,
                           y: bounds.maxY)
    guard let endCharacterRange = textView.characterRange(at: endPoint) else {
        return NSRange(location: 0, length: 0)
    }

    let endPosition = endCharacterRange.end
    
    let startIndex = textView.offset(from: textView.beginningOfDocument, to: startPosition)
    let endIndex = textView.offset(from: startPosition, to: endPosition)
    return NSRange(location: startIndex, length: endIndex)
}

使用示例,通过点击按钮调用:

@IBAction func buttonTapped(sender: AnyObject) {
    let range = visibleRangeOfTextView(textView: self.textView)

    // Note: "as NSString" won't work correctly with Emoji and stuff,
    // see also: http://stackoverflow.com/a/24045156/1085556
    let nsText = self.textView.text as NSString
    let text = nsText.substring(with: range)
    NSLog("range: \(range), text = \(text)")
}

相关问题