如何在swift中将字符索引从layoutManager转换为String scale? 这是我正在使用的代码:
let touchPoint: CGPoint = gesture.locationOfTouch(0, inView: self.definitionLabel)
let index = layoutManager.characterIndexForPoint(touchPoint, inTextContainer: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
请不要告诉我在字符串字符集的第一个索引上使用advanceBy()
函数,因为像ò这样的字符在layoutManager的规模中计数为2,但是swift字符串计数主题一次。
答案 0 :(得分:2)
从NSLayoutManager
返回的索引是" NSString
基于",
即它是字符串开头的UTF-16代码单元的数量
在给定点上的角色。 (所以ò
实际上算作
一个,但Emojis 计数两个,标志
计算四个。)
要将该索引转换为有效的Swift String
索引,您可以使用
与https://stackoverflow.com/a/30404532/1187415中的方法相同:
let text = ... // the stored text
let i16 = text.utf16.startIndex.advancedBy(index, limit: text.utf16.endIndex)
// i16 is a String.UTF16View.Index
if let strIndex = String.Index(i16, within: text) {
// strIndex is a String.CharacterView.Index
let char = text[strIndex]
print(char)
}
答案 1 :(得分:0)
已为Swift 5更新
马丁·R的回答给了我粗略的轮廓;这是工作中的Swift 5版本。我的是用于带有属性文本的UITextView,但应该与常规String以及UITextField和UILabel一起使用。
func handleTap(_ sender: UIGestureRecognizer) {
guard let textView = sender.view as? UITextView else { return }
guard let plaintext = textView.attributedText?.string else { return }
//guard let plaintext = textView.text else { return }
let location = sender.location(in: textView)
let charIndex = textView.layoutManager.characterIndex(for: location, in: textView.textContainer,
fractionOfDistanceBetweenInsertionPoints: nil)
if let strIndex = plaintext.utf16.index(plaintext.utf16.startIndex, offsetBy: charIndex, limitedBy: plaintext.utf16.endIndex) {
let char = plaintext[strIndex]
print("Character tapped was \(char)")
}
}
let textTap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
textView.addGestureRecognizer(textTap)