Skip to content

Instantly share code, notes, and snippets.

@iceboxi
Created October 25, 2018 08:03
Show Gist options
  • Select an option

  • Save iceboxi/cd94e3b038d0edbcec70e8e6779aff9f to your computer and use it in GitHub Desktop.

Select an option

Save iceboxi/cd94e3b038d0edbcec70e8e6779aff9f to your computer and use it in GitHub Desktop.

Revisions

  1. iceboxi created this gist Oct 25, 2018.
    48 changes: 48 additions & 0 deletions TapUILabel.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    @objc func tapLabel(gesture: UITapGestureRecognizer) {
    let text = (gesture.view as? UILabel)?.text ?? ""
    let termsRange = (text as NSString).range(of: "terms")
    let privacyRange = (text as NSString).range(of: "privacy")

    if gesture.didTapAttributedTextInLabel(label: guildLabel, inRange: termsRange) {
    print("Tapped terms")
    } else if gesture.didTapAttributedTextInLabel(label: guildLabel, inRange: privacyRange) {
    print("Tapped privacy")
    } else {
    print("Tapped none")
    }
    }

    extension UITapGestureRecognizer {
    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)

    return NSLocationInRange(indexOfCharacter, targetRange)
    }
    }