// // UITapGesture.swift // VDS // // Created by Matt Bruce on 8/4/22. // import Foundation import UIKit extension UITapGestureRecognizer { public func didTapAttributedTextInLabel(_ label: UILabel, inRange targetRange: NSRange) -> Bool { guard let abstractContainer = label.abstractTextContainer() else { return false } let textContainer = abstractContainer.0 let layoutManager = abstractContainer.1 let tapLocation = location(in: label) let indexOfGlyph = layoutManager.glyphIndex(for: tapLocation, in: textContainer) let intrinsicWidth = label.intrinsicContentSize.width // Assert that tapped occured within acceptable bounds based on alignment. switch label.textAlignment { case .right: if tapLocation.x < label.bounds.width - intrinsicWidth { return false } case .center: let halfBounds = label.bounds.width / 2 let halfIntrinsicWidth = intrinsicWidth / 2 if tapLocation.x > halfBounds + halfIntrinsicWidth { return false } else if tapLocation.x < halfBounds - halfIntrinsicWidth { return false } default: // Left align if tapLocation.x > intrinsicWidth { return false } } // Affirms that the tap occured in the desired rect of provided by the target range. return layoutManager.boundingRect(forGlyphRange: targetRange, in: textContainer).contains(tapLocation) && NSLocationInRange(indexOfGlyph, targetRange) } }