From c6ee16868bcf2a0d4f94502dcd4c83869a08a2d0 Mon Sep 17 00:00:00 2001 From: ALi Date: Mon, 29 Mar 2021 09:56:59 +0200 Subject: [PATCH 1/2] Fixed #2 Use tap gesture recognizer instead of direct event processing to avoid multiple tap processing --- ClickableLabel/InteractiveLinkLabel.swift | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/ClickableLabel/InteractiveLinkLabel.swift b/ClickableLabel/InteractiveLinkLabel.swift index 588b400..36dde15 100644 --- a/ClickableLabel/InteractiveLinkLabel.swift +++ b/ClickableLabel/InteractiveLinkLabel.swift @@ -22,12 +22,13 @@ class InteractiveLinkLabel: UILabel { func configure() { isUserInteractionEnabled = true + addGestureRecognizer(UITapGestureRecognizer.init(target: self, action: #selector(labelTapped))) } - override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { - - let superBool = super.point(inside: point, with: event) - + @objc private func labelTapped(_ recognizer: UITapGestureRecognizer) { + + guard let attributedText = attributedText else { return } + // Configure NSTextContainer let textContainer = NSTextContainer(size: bounds.size) textContainer.lineFragmentPadding = 0.0 @@ -38,7 +39,6 @@ class InteractiveLinkLabel: UILabel { let layoutManager = NSLayoutManager() layoutManager.addTextContainer(textContainer) - guard let attributedText = attributedText else {return false} // Configure NSTextStorage and apply the layout manager let textStorage = NSTextStorage(attributedString: attributedText) @@ -46,7 +46,7 @@ class InteractiveLinkLabel: UILabel { textStorage.addLayoutManager(layoutManager) // get the tapped character location - let locationOfTouchInLabel = point + let locationOfTouchInLabel = recognizer.location(in: self) // account for text alignment and insets let textBoundingBox = layoutManager.usedRect(for: textContainer) @@ -74,7 +74,7 @@ class InteractiveLinkLabel: UILabel { let rightMostPointInLineTapped = CGPoint(x: bounds.size.width, y: font.lineHeight * CGFloat(lineTapped)) let charsInLineTapped = layoutManager.characterIndex(for: rightMostPointInLineTapped, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil) - guard characterIndex < charsInLineTapped else {return false} + guard characterIndex < charsInLineTapped else { return } let attributeName = NSAttributedString.Key.link @@ -85,8 +85,6 @@ class InteractiveLinkLabel: UILabel { UIApplication.shared.open(url) } } - - return superBool - } + } From 100e902affeb759a1e428ea48e871760d104c6c3 Mon Sep 17 00:00:00 2001 From: ALi Date: Mon, 29 Mar 2021 09:58:18 +0200 Subject: [PATCH 2/2] Fix invalid font applying Remove direct font applying on text storage because it causes tap processing issues. The attributed string's already contained font information so it's not necessary to add font attribute to the text storage. --- ClickableLabel/InteractiveLinkLabel.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/ClickableLabel/InteractiveLinkLabel.swift b/ClickableLabel/InteractiveLinkLabel.swift index 36dde15..279e9ee 100644 --- a/ClickableLabel/InteractiveLinkLabel.swift +++ b/ClickableLabel/InteractiveLinkLabel.swift @@ -42,7 +42,6 @@ class InteractiveLinkLabel: UILabel { // Configure NSTextStorage and apply the layout manager let textStorage = NSTextStorage(attributedString: attributedText) - textStorage.addAttribute(NSAttributedString.Key.font, value: font!, range: NSMakeRange(0, attributedText.length)) textStorage.addLayoutManager(layoutManager) // get the tapped character location