Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display clickable links in UITextView

I am trying to display an attributed string in a UITextview with clickable links. I've created a simple test project to see where I'm going wrong and still can't figure it out. I've tried enabling user interaction and setting the shouldInteractWithURLs delegate method, but it's still not working. Here's my code (for a view controller that only contains a textview)

  @IBOutlet weak var textView: UITextView!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let string = "Google"
    let linkString = NSMutableAttributedString(string: string)
    linkString.addAttribute(NSLinkAttributeName, value: NSURL(string: "https://www.google.com")!, range: NSMakeRange(0, string.characters.count))
    linkString.addAttribute(NSFontAttributeName, value: UIFont(name: "HelveticaNeue", size: 25.0)!, range: NSMakeRange(0, string.characters.count))
    textView.attributedText = linkString
    textView.delegate = self
    textView.selectable = true
    textView.userInteractionEnabled = true
}

And here are the delegate methods I've implemented:

func textViewShouldBeginEditing(textView: UITextView) -> Bool {
    return false
}

func textView(textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {
    return true
}

This still isn't working. I've searched on this topic and nothing has helped yet. Thanks so much in advance.

like image 449
jhk727 Avatar asked Dec 22 '15 21:12

jhk727


People also ask

How can I make a clickable link in an Nsattributedstring?

You just set the "detect links" checkbox on the view in IB, and it detects HTTP links and turns them into hyperlinks. However, that still means that what the user sees is the "raw" link. RTF files and HTML both allow you to set up a user-readable string with a link "behind" it.

How do I change the color of a link in TextView Swift?

You can Change the Hyperlink Color in a TextView by the following: In the Nib file, you can go to the Properties Window and change the Tint to which ever color you want to.


Video Answer


3 Answers

Just select the UITextView in your storyboard and go to "Show Attributes inspector" and select selectable and links. As the image below shows. Make sure Editable is unchecked.

enter image description here

like image 129
Rashwan L Avatar answered Oct 20 '22 04:10

Rashwan L


For swift3.0

  override func viewDidLoad() {
     super.viewDidLoad()

  let linkAttributes = [
        NSLinkAttributeName: NSURL(string: "http://stalwartitsolution.co.in/luminutri_flow/terms-condition")!
        ] as [String : Any]
  let attributedString = NSMutableAttributedString(string: "Please tick box to confirm you agree to our Terms & Conditions, Privacy Policy, Disclaimer. ")

  attributedString.setAttributes(linkAttributes, range: NSMakeRange(44, 18))

  attributedString.addAttribute(NSUnderlineStyleAttributeName, value: NSNumber(value: 1), range: NSMakeRange(44, 18))

  textview.delegate = self
  textview.attributedText = attributedString
  textview.linkTextAttributes = [NSForegroundColorAttributeName: UIColor.red]
  textview.textColor = UIColor.white
  }


  func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
    return true
   }
like image 21
Maulik Patel Avatar answered Oct 20 '22 05:10

Maulik Patel


Swift 3 iOS 10: Here's Clickable extended UITextView that detect websites inside the textview automatically as long as the link start with www. for example: www.exmaple.com if it exist anywhere in the text will be clickable. Here's the class:

import Foundation
import UIKit




public class ClickableTextView:UITextView{



    var tap:UITapGestureRecognizer!
    override public init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        print("init")
        setup()
    }
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }


    func setup(){

        // Add tap gesture recognizer to Text View
        tap = UITapGestureRecognizer(target: self, action: #selector(self.myMethodToHandleTap(sender:)))
        //        tap.delegate = self
        self.addGestureRecognizer(tap)
    }

    func myMethodToHandleTap(sender: UITapGestureRecognizer){

        let myTextView = sender.view as! UITextView
        let layoutManager = myTextView.layoutManager

        // location of tap in myTextView coordinates and taking the inset into account
        var location = sender.location(in: myTextView)
        location.x -= myTextView.textContainerInset.left;
        location.y -= myTextView.textContainerInset.top;


        // character index at tap location
        let characterIndex = layoutManager.characterIndex(for: location, in: myTextView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)

        // if index is valid then do something.
        if characterIndex < myTextView.textStorage.length {

            let orgString = myTextView.attributedText.string


            //Find the WWW
            var didFind = false
            var count:Int = characterIndex
            while(count > 2 && didFind == false){

                let myRange = NSRange(location: count-1, length: 2)
                let substring = (orgString as NSString).substring(with: myRange)

//                print(substring,count)

                if substring == " w" || (substring  == "w." && count == 3){
                    didFind = true
//                    print("Did find",count)

                    var count2 = count
                    while(count2 < orgString.characters.count){

                        let myRange = NSRange(location: count2 - 1, length: 2)
                        let substring = (orgString as NSString).substring(with: myRange)

//                        print("Did 2",count2,substring)
                        count2 += 1


                        //If it was at the end of textView
                        if count2  == orgString.characters.count {

                            let length = orgString.characters.count - count
                            let myRange = NSRange(location: count, length: length)

                            let substring = (orgString as NSString).substring(with: myRange)

                            openLink(link: substring)
                            print("It's a Link",substring)
                            return
                        }

                        //If it's in the middle

                        if substring.hasSuffix(" "){

                            let length =  count2 - count
                            let myRange = NSRange(location: count, length: length)

                            let substring = (orgString as NSString).substring(with: myRange)

                            openLink(link: substring)
                            print("It's a Link",substring)

                            return
                        }

                    }

                    return
                }


                if substring.hasPrefix(" "){

                    print("Not a link")
                    return
                }

                count -= 1

            }


        }


    }


    func openLink(link:String){

        if let checkURL = URL(string: "http://\(link.replacingOccurrences(of: " ", with: ""))") {
            if UIApplication.shared.canOpenURL(checkURL) {
                UIApplication.shared.open(checkURL, options: [:], completionHandler: nil)

                print("url successfully opened")
            }
        } else {
            print("invalid url")
        }
    }


    public override func didMoveToWindow() {
        if self.window == nil{
            self.removeGestureRecognizer(tap)
            print("ClickableTextView View removed from")
        }
    }
}
like image 23
Jad Avatar answered Oct 20 '22 06:10

Jad