获取当前段落索引

Get Current Paragraph Index

我想找到用户正在输入的当前段落(插入符所在的位置)。 示例:这里是第 2 段。

我知道我可以使用以下方式分隔段落:let components = textView.text.components(separatedBy: "\n") 但我不确定如何 运行 检查当前编辑的段落。有什么想法吗?

这是一种方法...

获取插入符号(插入点)的 Y 位置。然后,循环遍历 textView 中的段落枚举,将它们的边界矩形与插入符号位置进行比较:

extension UITextView {

    func boundingFrame(ofTextRange range: Range<String.Index>?) -> CGRect? {

        guard let range = range else { return nil }
        let length = range.upperBound.encodedOffset-range.lowerBound.encodedOffset
        guard
            let start = position(from: beginningOfDocument, offset: range.lowerBound.encodedOffset),
            let end = position(from: start, offset: length),
            let txtRange = textRange(from: start, to: end)
            else { return nil }

        return selectionRects(for: txtRange).reduce(CGRect.null) { [=10=].union(.rect) }

    }

}

// return value will be Zero-based index of the paragraphs
// if the textView has no text, return -1
@objc func getParagraphIndex(in textView: UITextView) -> Int {

    // this will make sure the the text container has updated
    theTextView.layoutManager.ensureLayout(for: theTextView.textContainer)

    // make sure we have some text
    guard let str = theTextView.text else { return -1 }

    // get the full range
    let textRange = str.startIndex..<str.endIndex

    // we want to enumerate by paragraphs
    let opts:NSString.EnumerationOptions = .byParagraphs

    var caretYPos = CGFloat(0)
    if let selectedTextRange = theTextView.selectedTextRange {
        caretYPos = theTextView.caretRect(for: selectedTextRange.start).origin.y + 4
    }

    var pIndex = -1
    var i = 0

    // loop through the paragraphs, comparing the caret Y position to the paragraph bounding rects
    str.enumerateSubstrings(in: textRange, options: opts) {
        (substring, substringRange, enclosingRange, b) in

        // get the bounding rect for the sub-rects in each paragraph
        if let boundRect = self.theTextView.boundingFrame(ofTextRange: substringRange) {

            if caretYPos > boundRect.origin.y && caretYPos < boundRect.origin.y + boundRect.size.height {
                pIndex = i
                b = true
            }

            i += 1
        }
    }

    return pIndex
}

用法:

let paraIndex = getParagraphIndex(in myTextView)