Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在UITextView中滚动后获取可见文本的NSRange_Ios_Swift_Uitextview_Nsrange - Fatal编程技术网

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

Ios 在UITextView中滚动后获取可见文本的NSRange,ios,swift,uitextview,nsrange,Ios,Swift,Uitextview,Nsrange,我正在尝试将滚动文本的位置保存在UITextView中,以便在再次加载ViewController时返回到该位置。我有很长的字符串,所以我希望用户能够滚动到特定位置,然后稍后返回到该位置 我正在使用UITextView。scrollRangeToVisible函数自动滚动文本视图,但我不知道如何获取用户看到的文本的NSRange。这是最好的方法吗?我试着使用setContentOffset函数,但似乎没有任何效果 感谢您的帮助。谢谢 我还没有彻底测试过这一点,但我相信下面的方法应该有效。您需要的

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

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


感谢您的帮助。谢谢

我还没有彻底测试过这一点,但我相信下面的方法应该有效。您需要的API记录在协议中,
UITextView
采用该协议

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

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
进行实验,以获得所需的结果。

这里是
UITextView
的一个小扩展,它使用了
characterRange(at:)
函数。它还添加了一个计算属性以返回当前可见的文本:

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)
    }

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

extension CGRect {

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

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

}

为了产生这个问题,你能分享一些代码吗?谢谢,这很有帮助。我尝试实现这一点,在bounds.maxY之外创建一个CGPoint,而不是使用bounds.origin。这在正文的第一季度非常有效,但在那之后它又开始回到开头,这很奇怪。嗯,这对我来说似乎很有效。我编辑了我的答案,以包含一个更完整的代码示例。我只是在一个操场上用大约3000个字符的纯文本(无格式)对此进行了测试,但我已确认报告的值是准确的。