If you want this to be handled using a UILabel rather than a UITextView, you can subclass UILabel like this:
class LinkedLabel: UILabel { fileprivate let layoutManager = NSLayoutManager() fileprivate let textContainer = NSTextContainer(size: CGSize.zero) fileprivate var textStorage: NSTextStorage? override init(frame aRect:CGRect){ super.init(frame: aRect) self.initialize() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.initialize() } func initialize(){ let tap = UITapGestureRecognizer(target: self, action: #selector(LinkedLabel.handleTapOnLabel)) self.isUserInteractionEnabled = true self.addGestureRecognizer(tap) } override var attributedText: NSAttributedString?{ didSet{ if let _attributedText = attributedText{ self.textStorage = NSTextStorage(attributedString: _attributedText) self.layoutManager.addTextContainer(self.textContainer) self.textStorage?.addLayoutManager(self.layoutManager) self.textContainer.lineFragmentPadding = 0.0; self.textContainer.lineBreakMode = self.lineBreakMode; self.textContainer.maximumNumberOfLines = self.numberOfLines; } } } func handleTapOnLabel(tapGesture:UITapGestureRecognizer){ let locationOfTouchInLabel = tapGesture.location(in: tapGesture.view) let labelSize = tapGesture.view?.bounds.size let textBoundingBox = self.layoutManager.usedRect(for: self.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 = self.layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: self.textContainer, fractionOfDistanceBetweenInsertionPoints: nil) self.attributedText?.enumerateAttribute(NSLinkAttributeName, in: NSMakeRange(0, (self.attributedText?.length)!), options: NSAttributedString.EnumerationOptions(rawValue: UInt(0)), using:{ (attrs: Any?, range: NSRange, stop: UnsafeMutablePointer<ObjCBool>) in if NSLocationInRange(indexOfCharacter, range){ if let _attrs = attrs{ UIApplication.shared.openURL(URL(string: _attrs as! String)!) } } }) }}
This class was created by reusing the code from this. To attribute strings, execute this answer . And here you can find how to make phone URLs.
Bojan Bozovic Nov 22 '16 at 16:35 2016-11-22 16:35
source share