code: with this code edit profile
showing in blue colour but tap gesture not working.. if i click on "edit profile" then the its always goes to tapLabel
method's else part
always prints print("Tapped none")
... where am i wrong. please guide
fileprivate let text = "You have not completed your profile. Kindly go to edit profile and complete your profile."
class DashboardVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.yellowLabel.isUserInteractionEnabled = true
underlinetermsAndPolicy()
}
let termsRange = (text as NSString).range(of: "edit profile")
@objc func tapLabel(gesture: UITapGestureRecognizer) {
view.endEditing(true)
if gesture.didTapAttributedTextInLabel(label: yellowLabel, inRange: termsRange) {
print("Tapped profile")
}
else {
print("Tapped none")
}
}
func underlinetermsAndPolicy(){
yellowLabel.text = text
let clickableString = NSMutableAttributedString(string: yellowLabel.text!)
clickableString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.blue, range: termsRange)
yellowLabel.attributedText = clickableString
yellowLabel.addGestureRecognizer(UITapGestureRecognizer(target:self, action: #selector(tapLabel(gesture:))))
}
}
extension code:
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)
}
}
in console always prints this:
Tapped none
CodePudding user response:
Replace below line in the UITapGestureRecognizer extension
let textStorage = NSTextStorage(attributedString: label.attributedText!)
with following one
let textStorage = NSTextStorage(string: label.text ?? "")
CodePudding user response:
I think the locationOfTouchInTextContainer
you have calculate wrong.
Try this instead
let locationOfTouchInLabel = self.location(in: label)
var textBoundingBox = layoutManager.usedRect(for: textContainer)
textBoundingBox.origin = CGPoint(x: label.bounds.midX - textBoundingBox.size.width / 2, y: label.bounds.midY - textBoundingBox.size.height / 2)
let touchPoint = CGPoint(x: locationOfTouchInLabel.x - textBoundingBox.origin.x, y: locationOfTouchInLabel.y - textBoundingBox.origin.y)
let index = layoutManager.characterIndex(for: touchPoint, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)