首页 > 解决方案 > 如何准确检测是否在 Swift 4 中的 UILabel 中单击了链接?

问题描述

编辑

请参阅我的答案以获得完整的工作解决方案:

我设法通过使用 aUITextView而不是 a自己解决了这个问题UILabel。我写了一个类,它使UITextView行为像一个UILabel但具有完全准确的链接检测。


我已经设法毫无问题地设置链接的样式,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)
}

标签: iosxcodeuilabelswift4nsattributedstring

解决方案


如果你不介意重写你的代码,你应该使用UITextView而不是UILabel.

UITextView您可以通过设置'轻松检测链接dataDetectorTypes并实现委托功能以检索您点击的 url。

func textView(_ textView: UITextView, shouldInteractWith URL: URL, 
    in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool

https://developer.apple.com/documentation/uikit/uitextviewdelegate/1649337-textview


推荐阅读