UITextInput.characterRange(at :)偏离了几个像素 [英] UITextInput.characterRange(at:) is off by a few pixels
问题描述
在我的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)
}
}
问题是,如果我的attributedText是"Hello world\nWelcome to Stack Overflow"
,并且我点击了字母的左侧部分(例如字母f
的左侧),则characterRange(at: location)
返回前一个字母r
而不是返回
从我的角度来看,光标在该位置的位置"功能,这使得确定哪个字符实际上不可靠:它是光标或光标之前的字符吗?光标后的字符?
closestPosition(to:)
遭受完全相同的问题./p>
一种可行的替代方法是 layoutManager.characterIndex(for:in:fractionOfDistanceBetweenInsertionPoints:)
. 授予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)
}
After adding a tap recognizer to my UITextView
subclass, I'm attempting to get the character that is being tapped:
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)
}
}
Problem is that if my attributedText is "Hello world\nWelcome to Stack Overflow"
and I tap on the left part of a letter, like the left side of letter f
, then characterRange(at: location)
returns the previous letter r
instead of returning f
.
From my perspective, characterRange(at:)
is buggy:
- If you give it a point on the left half of character at index
n
, it returns range(n-1, n)
- If you give it a point on the right half of character at index
n
, it returns range(n, n+1)
- If you give it a point on the left half of character at index
beginningOfDocument
, it returnsnil
- If you give it a point on the right half of character at index
endOfDocument
, it returns(endOfDocument, endOfDocument+1)
The discrepancy of the behaviors at the extremities of the textInput demonstrate that there is a bug somewhere.
It behaves like a sort of "cursor position at point" function, which makes it unreliable to determine which character is actually at this point: is it the character before the cursor or the character after the cursor?
closestPosition(to:)
suffers from the exact same issue.
A working alternative is 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)
}
这篇关于UITextInput.characterRange(at :)偏离了几个像素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!