How to make URL/Phone-clickable UILabel?

IphoneObjective CUrlUilabel

Iphone Problem Overview


I want to create a clickable label on my app leading me to a Safari webpage. I also want the user to be able to phone the numbers only by clicking on them ?

Thanks for your advices

Iphone Solutions


Solution 1 - Iphone

You can use a UITextView and select Detection for Links, Phone Numbers and other things in the inspector.

Solution 2 - Iphone

Use UITextView instead of UILabel and it has a property to convert your text to hyperlink.

###Objective-C:

yourTextView.editable = NO;
yourTextView.dataDetectorTypes = UIDataDetectorTypeAll;

###Swift:

yourTextView.editable = false; 
yourTextView.dataDetectorTypes = UIDataDetectorTypes.All;

This will detect links automatically.

See the documentation for details.

Solution 3 - Iphone

https://github.com/mattt/TTTAttributedLabel

That's definitely what you need. You can also apply attributes for your label, like underline, and apply different colors to it. Just check the instructions for clickable urls.

Mainly, you do something like the following:

NSRange range = [label.text rangeOfString:@"me"];
[label addLinkToURL:[NSURL URLWithString:@"http://github.com/mattt/"] withRange:range]; // Embedding a custom link in a substring

Solution 4 - Iphone

You can make a custom UIButton and setText what ever you want and add a method with that.

UIButton *sampleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[sampleButton setFrame:CGRectMake(kLeftMargin, 10, self.view.bounds.size.width - kLeftMargin - kRightMargin, 52)];
[sampleButton setTitle:@"URL Text" forState:UIControlStateNormal];
[sampleButton setFont:[UIFont boldSystemFontOfSize:20]];


[sampleButton addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sampleButton];


-(void)buttonPressed:(id)sender{
  // open url
}

Solution 5 - Iphone

If you want this to be handled by UILabel and not UITextView, you can make UILabel subclass, like this one:

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 made by reusing code from this answer. In order to make attributed strings check out this answer. And here you can find how to make phone urls.

Solution 6 - Iphone

Use this i liked it so much since creates link with blue color to particular text only not on whole label text: FRHyperLabel

Smartly applying hyperlink on Terms of Use

To do:

  1. Download from above link and copy FRHyperLabel.h, FRHyperLabel.m to your project.

  2. Drag drop UILabel in your Storyboard and define custom class name to FRHyperLabel in identify inspector as shown in image.

enter image description here

  1. Connect your UILabel from storyboard to your viewController.h file

@property (weak, nonatomic) IBOutlet FRHyperLabel *label;

  1. Now in your viewController.m file add following code.

`NSString *string = @"By uploading I agree to the Terms of Use"; NSDictionary *attributes = @{NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]};

_label.attributedText = [[NSAttributedString alloc]initWithString:string attributes:attributes];
[_label setFont:[_label.font fontWithSize:13.0]];

[_label setLinkForSubstring:@"Terms of Use" withLinkHandler:^(FRHyperLabel *label, NSString *substring){
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.google.com"]];
}];`

5. And run it.

Solution 7 - Iphone

Use UITextView instead of UILabel and it has a property to convert your text to hyperlink

Swift code:

yourTextView.editable = false
yourTextView.dataDetectorTypes = UIDataDetectorTypes.All
//or
yourTextView.dataDetectorTypes = UIDataDetectorTypes.PhoneNumber
//or
yourTextView.dataDetectorTypes = UIDataDetectorTypes.Link

Solution 8 - Iphone

extension UITapGestureRecognizer {
    
    func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
        
        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
        textContainer.size = label.bounds.size
        
        // main code
        let locationOfTouchInLabel = self.location(in: label)
        
        let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInLabel, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
        let indexOfCharacterRange = NSRange(location: indexOfCharacter, length: 1)
        let indexOfCharacterRect = layoutManager.boundingRect(forGlyphRange: indexOfCharacterRange, in: textContainer)
        let deltaOffsetCharacter = indexOfCharacterRect.origin.x + indexOfCharacterRect.size.width
        
        if locationOfTouchInLabel.x > deltaOffsetCharacter {
            return false
        } else {
            return NSLocationInRange(indexOfCharacter, targetRange)
        }
    }
}

Solution 9 - Iphone

Why not just use NSMutableAttributedString?

let attributedString = NSMutableAttributedString(string: "Want to learn iOS? Just visit developer.apple.com!")
        attributedString.addAttribute(.link, value: "https://developer.apple.com", range: NSRange(location: 30, length: 50))

        myView.attributedText = attributedString

You can find more details here

Solution 10 - Iphone

Swift 4.0 possible solution using UIButton

     phoneButton = UIButton(frame: CGRect(x: view.frame.width * 0, y: view.frame.height * 0.1, width: view.frame.width * 1, height: view.frame.height * 0.05))
     phoneButton.setTitle("333-333-3333", for: .normal )
     phoneButton.setTitleColor(UIColor(red: 0 / 255, green: 0 / 255, blue: 238 / 255, alpha: 1.0), for: .normal)
     phoneButton.addTarget(self, action: #selector(self.callPhone), for: .touchUpInside )

     @objc func callPhone(){

         UIApplication.shared.open(URL(string:"tel://3333333333")!, options: [:] , completionHandler: nil)
    
    
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRobView Question on Stackoverflow
Solution 1 - IphoneBaselView Answer on Stackoverflow
Solution 2 - IphoneSameera ChathurangaView Answer on Stackoverflow
Solution 3 - IphoneRamy KfouryView Answer on Stackoverflow
Solution 4 - IphoneRohit DhawanView Answer on Stackoverflow
Solution 5 - IphoneBojan BozovicView Answer on Stackoverflow
Solution 6 - IphonekaranView Answer on Stackoverflow
Solution 7 - IphoneThiago ArreguyView Answer on Stackoverflow
Solution 8 - IphoneHarmanView Answer on Stackoverflow
Solution 9 - IphoneMANNView Answer on Stackoverflow
Solution 10 - IphoneFidelView Answer on Stackoverflow