Я использую этот метод для обнаружения кликов по хэштегам и другим ссылкам в UILabel.
Этот код работает нормально, возвращая истинное значение в большинстве случаев, но в случае, если приписанный текст содержит некоторые юникоды, такие как emojis, этот метод завершается ошибкой и возвращает ложное значение.
Я отладилон обнаружил, что этот метод layoutManager.glyphIndex(for: locationOfTouchInLabel, in: textContainer, fractionOfDistanceThroughGlyph: nil)
предоставляет неверное значение индекса.
public func isTouchInLabelRange(touch: UITouch, label: UILabel, inRange targetRange: NSRange) -> Bool {
guard let attributedText = label.attributedText else {
return false
}
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: CGSize.zero)
let textStorage = NSTextStorage(attributedString: attributedText)
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
textContainer.lineFragmentPadding = 0.0
textContainer.lineBreakMode = label.lineBreakMode
textContainer.heightTracksTextView = true
textContainer.maximumNumberOfLines = label.numberOfLines
let labelSize = label.bounds.size
textContainer.size = labelSize
let locationOfTouchInLabel = touch.location(in: label)
let indexOfCharacter = layoutManager.glyphIndex(for: locationOfTouchInLabel, in: textContainer, fractionOfDistanceThroughGlyph: nil)
let bufferIndex = 2
let updatedTargetRange = NSRange.init(location: targetRange.location > bufferIndex ? targetRange.location-bufferIndex : targetRange.location , length: targetRange.length + 2*bufferIndex)
return NSLocationInRange(Int(indexOfCharacter), updatedTargetRange)
}