0

I have a UITextView and NSMutableAttributedString which has a clickable link. I need this to show another storyboard but not quite sure how I could do this.

What I have so far works for external links but not a storyboard. Any help would be appreciated.

Not sure if the below code is the best way to approach it or not?

class HomeViewController: UIViewController {

    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let attributedString = NSMutableAttributedString(string: "Already have an account? Log in")
        attributedString.addAttribute(.link, value: "", range: NSRange(location: 25, length: 6))

        textView.attributedText = attributedString

    }

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        UIApplication.shared.open(URL)

        return false
    }


}

EDIT

After NikR answer I've updated my code to the following but still no success. It's still loading Google.

class HomeViewController: UIViewController, UITextViewDelegate {

    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let attributedString = NSMutableAttributedString(string: "Already have an account? Log in")
        attributedString.addAttribute(.link, value: "https://google.com", range: NSRange(location: 25, length: 6))

        textView.attributedText = attributedString
        textView.isSelectable = true
        textView.isEditable = false

        textView.delegate = self

    }

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {

        let loginViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "loginViewController")
        show(loginViewController, sender: self)

        return true
    }


}
CIB
  • 535
  • 1
  • 12
  • 35

3 Answers3

0

Yes it's the right way. But not call:

UIApplication.shared.open(URL)

Simply initiate your VC and show/present it:

let vc = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateInitialViewController()
show( vc, sender: self )

And don't forget to:

textView.delegate = self
NikR
  • 628
  • 4
  • 14
  • The controller I want to show uses the same story board so I dont think I can use the ```instantiateInitialViewController ``` So I used ```let loginViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController")``` Should this still work? – CIB Jun 11 '19 at 11:58
  • Yes, it should. – NikR Jun 11 '19 at 11:58
  • I get this message in my console ```Could not find any actions for URL without any result.``` – CIB Jun 11 '19 at 12:01
  • Try to set some real URL in value with "https://", seems that it tries to parse url but cannot without a scheme – NikR Jun 11 '19 at 13:15
  • I tried that so if I pass ```https://google.com``` when the login link is clicked it opens safari and goes to google. It doesn't show my LoginViewController – CIB Jun 11 '19 at 13:20
  • Check that textView.delegate = self – NikR Jun 11 '19 at 13:41
  • Yeah I've added ```textView.delegate = self ``` i've updated my question to have the full code in there from your answer. – CIB Jun 11 '19 at 14:12
  • 1
    @craigib, you should return false from textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool . It will not pass control to iOS and allows you to handle it by youself – NikR Jun 11 '19 at 16:23
  • This worked, along with your original answer. Thanks – CIB Jun 11 '19 at 19:17
0

you can set to your textView:

textView.dataDetectorTypes = .link
Alastar
  • 1,284
  • 1
  • 8
  • 14
0

You should enable isSelectable and disable isEditable for your text view.

textView.isSelectable = true
textView.isEditable = false

Don't forget to do this

textView.delegate = self

This Delegate method will use to handle click

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {

}
Rohit Parihar
  • 352
  • 1
  • 7
  • 14
  • When I add ```textView.delegate = self``` to my viewDidfLoad I get an error ```Cannot assign value of type 'HomeViewController' to type 'UITextViewDelegate?'``` – CIB Jun 11 '19 at 11:59
  • 1
    Replace class HomeViewController: UIViewController with class HomeViewController: UIViewController, UITextViewDelegate for implement delegate methods for UITextView. – Rohit Parihar Jun 11 '19 at 12:25
  • 1
    Or Just under your implementation extension HomeViewController: UITextViewDelegate { //... } – NikR Jun 11 '19 at 13:43
  • @NikR yes we can also add extension for UITextViewDelegate under class implementation – Rohit Parihar Jun 11 '19 at 14:04