获取当前段落索引

时间:2019-06-26 12:32:45

标签: ios swift uitextview

我想查找用户正在输入的当前段落(插入符号所在的位置)。 示例:这将在第二段中。

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

1 个答案:

答案 0 :(得分:0)

这是一种方法...

获取插入符的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) { $0.union($1.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)