I am using this method to detect click on hashtags and other attributed links in the UILabel.
This code works fine by returning true value in most of the cases but in case the attributed text contains some unicodes like emojis then this methods fails and return false as a value.
I have debugged it and found that that method layoutManager.glyphIndex(for: locationOfTouchInLabel, in: textContainer, fractionOfDistanceThroughGlyph: nil)
is providing wrong index value.
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)
}