【问题标题】:UITextInput.characterRange(at:) is off by a few pixelsUITextInput.characterRange(at:) 偏离了几个像素
【发布时间】:2018-09-08 03:46:24
【问题描述】:

在我的UITextView 子类中添加点击识别器后,我正在尝试获取被点击的字符:

var textRecognizer: UITapGestureRecognizer!
required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    textContainer.lineFragmentPadding = 0
    textContainerInset = .zero

    textRecognizer = UITapGestureRecognizer(target: self, action: #selector(textTapped))
    textRecognizer.numberOfTapsRequired = 1
    addGestureRecognizer(textRecognizer)
}

@objc func textTapped(recognizer: UITapGestureRecognizer) {
    let location = recognizer.location(in: self)
    if let cRange = characterRange(at: location) {
        let cPosition = offset(from: beginningOfDocument, to: cRange.start)
        let cChar = text[Range(NSRange(location: cPosition, length: 1), in: text)!]
        print(cChar)
    }
}

问题是,如果我的属性文本是 "Hello world\nWelcome to Stack Overflow" 并且我点击字母的左侧,例如字母 f 的左侧,那么 characterRange(at: location) 返回上一个字母 r 而不是返回 @987654327 @。

【问题讨论】:

    标签: ios uitextview uigesturerecognizer uitextinput uitextposition


    【解决方案1】:

    在我看来,characterRange(at:) 有问题:

    • 如果你在索引n处的字符左半边给它一个点,它返回范围(n-1, n)
    • 如果你在索引n处的字符右半边给它一个点,它返回范围(n, n+1)
    • 如果你在索引beginningOfDocument处的字符左半边给它一个点,它返回nil
    • 如果你在索引endOfDocument处的字符右半边给它一个点,它返回(endOfDocument, endOfDocument+1)

    textInput 末端行为的差异表明某处存在错误。

    它的行为类似于“光标在点的位置”函数,这使得确定哪个字符实际上在这一点是不可靠的:是光标之前的字符还是光标后的字符?

    closestPosition(to:) 遇到完全相同的问题。

    一个可行的替代方案是layoutManager.characterIndex(for:in:fractionOfDistanceBetweenInsertionPoints:)Credit to vacawama:

    @objc func textTapped(recognizer: UITapGestureRecognizer) {
        var location = recognizer.location(in: self)
        location.x -= textContainerInset.left
        location.y -= textContainerInset.top
        let cPosition = layoutManager.characterIndex(for: location, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
        let cChar = text[Range(NSRange(location: cPosition, length: 1), in: text)!]
        print(cChar)
    }
    

    【讨论】:

      猜你喜欢
      • 2020-02-13
      • 2020-05-11
      • 1970-01-01
      • 2014-11-06
      • 1970-01-01
      • 1970-01-01
      • 2019-06-07
      • 2021-02-12
      • 2022-06-15
      相关资源
      最近更新 更多