редактировать
См. Мой ответ для полного рабочего решения:
Мне удалось решить это самостоятельно, используя UITextView
вместо UILabel
. Я написал класс, который заставляет UITextView
вести себя как UILabel
но с полностью точным обнаружением ссылок.
Мне удалось NSMutableAttributedString
ссылки без проблем с помощью NSMutableAttributedString
но я не могу точно определить, какой символ был нажат. Я пробовал все решения в этом вопросе (что я мог бы преобразовать в код Swift 4), но не повезло.
Следующий код работает, но не позволяет точно определить, какой символ был нажат, и получает неправильное расположение ссылки:
func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: CGSize.zero)
let textStorage = NSTextStorage(attributedString: label.attributedText!)
// Configure layoutManager and textStorage
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
// Configure textContainer
textContainer.lineFragmentPadding = 0.0
textContainer.lineBreakMode = label.lineBreakMode
textContainer.maximumNumberOfLines = label.numberOfLines
let labelSize = label.bounds.size
textContainer.size = labelSize
// Find the tapped character location and compare it to the specified range
let locationOfTouchInLabel = self.location(in: label)
let textBoundingBox = layoutManager.usedRect(for: textContainer)
let textContainerOffset = CGPoint(x: (labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, y: (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)
let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, y: locationOfTouchInLabel.y - textContainerOffset.y)
let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
print(indexOfCharacter)
return NSLocationInRange(indexOfCharacter, targetRange)
}