首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在UITextView中滚动后获取可见文本的NSRange

在UITextView中滚动后获取可见文本的NSRange
EN

Stack Overflow用户
提问于 2018-06-30 02:16:49
回答 2查看 867关注 0票数 3

我正在尝试将滚动文本的位置保存在UITextView中,以便在再次加载ViewController时可以返回到该位置。我有非常长的字符串,所以我希望用户能够滚动到特定位置,然后稍后返回到该位置。

我在用UITextView。scrollRangeToVisible函数用于自动滚动文本视图,但我不知道如何获取用户正在查看的文本的NSRange。这是最好的方法吗?我尝试使用setContentOffset函数,但似乎没有任何作用。

任何帮助都是非常感谢的。谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-30 03:57:09

我还没有对此进行彻底的测试,但我相信下面的方法应该是可行的。您需要的API记录在UITextView采用的UITextInput协议中。

您首先需要获取与视图内给定点相对应的UITextPosition。然后将该值转换为UTF-16字符偏移量。例如,每次滚动视图时,我都会打印textView的可视文本范围(以UTF-16代码单位表示):

代码语言:javascript
复制
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let topLeft = CGPoint(x: textView.bounds.minX, y: textView.bounds.minY)
    let bottomRight = CGPoint(x: textView.bounds.maxX, y: textView.bounds.maxY)
    guard let topLeftTextPosition = textView.closestPosition(to: topLeft),
        let bottomRightTextPosition = textView.closestPosition(to: bottomRight)
        else {
            return
    }
    let charOffset = textView.offset(from: textView.beginningOfDocument, to: topLeftTextPosition)
    let length = textView.offset(from: topLeftTextPosition, to: bottomRightTextPosition)
    let visibleRange = NSRange(location: charOffset, length: length)
    print("Visible range: \(visibleRange)")
}

在我的测试中,UITextView倾向于计算几乎不包含在可见范围内的线条(例如,只有一个像素),因此报告的可见范围往往比人类用户所说的大一到两条线。您可能需要尝试传递给closesPosition(to:)的确切CGPoint,才能获得您想要的结果。

票数 1
EN

Stack Overflow用户

发布于 2018-12-27 14:35:44

下面是使用其characterRange(at:)函数的UITextView上的一个小扩展。它还添加了一个计算属性来返回当前可见的文本:

代码语言:javascript
复制
extension UITextView {

    private var firstVisibleCharacterPosition: UITextPosition? {
        // ⚠️ For some reason `characterRange(at:)` returns nil for points with a low y value.
        guard let scrolledPosition = characterRange(at: contentOffset)?.start else {
            return beginningOfDocument
        }
        return scrolledPosition
    }

    private var lastVisibleCharacterPosition: UITextPosition? {
        return characterRange(at: bounds.max)?.end
    }

    /// The range of the text that is currently displayed within the text view's bounds.
    var visibleTextRange: UITextRange? {

        guard
            let first = firstVisibleCharacterPosition,
            let last = lastVisibleCharacterPosition else {
                return nil
        }

        return textRange(from: first, to: last)
    }      

    /// The string that is currently displayed within the text view's bounds.
    var visibleText: String? {
        guard let visibleTextRange = visibleTextRange else {
            return nil
        }
        return text(in: visibleTextRange)
    }

}

我在上面的代码中使用了这些速记属性:

代码语言:javascript
复制
extension CGRect {

    var min: CGPoint {
        return .init(x: minX, y: minY)
    }

    var max: CGPoint {
        return .init(x: maxX, y: maxY)
    }

}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51107371

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档