1

My goal is to log all the links that the user clicks on. The links are embedded in a UITextView inside a table cell, and when a user presses the link, I want it to call a function that prints the url.

I've looked at similar questions such as How to detect if a link, inside a UITextView has been clicked, Swift and How to intercept click on link in UITextView? where people have suggested using the function shouldInteractWithURL, but the function never gets called.

I think I might have set the delegate or the function in the wrong place, and it would be great if somebody could let me know how it should be setup.

Here are the abbreviated code and some screenshots of the page:

class BSPdetailViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate {


    func textView(textView: UITextView!, shouldInteractWithURL URL: NSURL!, inRange characterRange: NSRange) -> Bool {
        print("Link Selected!")
        return true

    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "detailCell", for: indexPath as IndexPath) as! detailCell
        cell.label?.text = ""


        cell.detailLinks.delegate = self
        cell.detailLinks.isUserInteractionEnabled = true // default: true
        cell.detailLinks.isEditable = false // default: true
        cell.detailLinks.isSelectable = true // default: true
        cell.detailLinks.dataDetectorTypes = [.link]

        cell.detailTextLabel?.font = UIFont.fontAwesome(ofSize: 20)
        cell.detailTextLabel?.text = ""
        cell.detailTextLabel?.numberOfLines = 0;


        cell.detailLinks?.text = "links are here"
        var linkString = NSMutableAttributedString(string: "", attributes: [NSFontAttributeName:UIFont.systemFont(ofSize: 22.0)])
        let video =  String.fontAwesomeIcon(code: "fa-video-camera")! + "  "
        let document = String.fontAwesomeIcon(code: "fa-file-text")! + "\n\n"

        for i in 0..<stratList.count {
            var stratURL = stratList[i].lowercased().replacingOccurrences(of: " ", with: "-")

            var docLink = "http://" + stratURL
            var videoLink = "http://" + stratURL

            //setting the url
            var attributedString = NSMutableAttributedString(string: video, attributes: [NSFontAttributeName: UIFont.fontAwesome(ofSize: 22)])
            attributedString.addAttribute(NSLinkAttributeName, value: docLink, range: NSRange(location: 0, length: 1))
            linkString.append(attributedString as NSAttributedString)

            attributedString = NSMutableAttributedString(string: document, attributes: [NSFontAttributeName: UIFont.fontAwesome(ofSize: 22)])
            attributedString.addAttribute(NSLinkAttributeName, value: videoLink, range: NSRange(location: 0, length: 1))
            linkString.append(attributedString as NSAttributedString)


            cell.label?.text = (cell.label?.text)! + "• " + stratList[i] + "\n\n"


            cell.detailLinks?.attributedText = linkString

            //tried tapgesture but it didn't work when I tapped on the links
            //cell.detailLinks.addGestureRecognizer(UITapGestureRecognizer(target: cell.detailLinks, action: #selector(cell.detailLinks.singleTap(tap:))))

            cell.backgroundColor = contentColors[rowNo]
            cell.label?.textColor = UIColor.black
        }


        return cell
    }
}

class detailCell: UITableViewCell
{

    @IBOutlet weak var detailLinks: UITextView!
    @IBOutlet weak var label: UILabel!

}

enter image description here

The resulting table: enter image description here

haedaldal
  • 71
  • 10

1 Answers1

3

UITextViewDelegate methods shouldInteractWithURL should be written outside of cellForRowAt not inside. Your standard UITextView setup should look something like this, don't forget the delegate and dataDetectorTypes.

    cell.detailLinks.delegate = self
    detailLinks.isUserInteractionEnabled = true // default: true
    detailLinks.isEditable = false // default: true
    detailLinks.isSelectable = true // default: true
    detailLinks.dataDetectorTypes = [.link]

UITextViewDelegate method shouldInteractWithURL:

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
    print("Link Selected!")
    return true
}
Govind Kumawat
  • 1,562
  • 1
  • 10
  • 17
  • Thanks again! I have tried these, and the function still isn't called. I have updated the code to reflect your suggestions. – haedaldal Jun 17 '18 at 04:58
  • 1
    @haedaldal the problem here is with your `UITextViewDelegate` method `shouldInteractWithURL` you are using the wrong method which have one parameter missing maybe it's used in previous swift version. – Govind Kumawat Jun 17 '18 at 07:52
  • This really saved me. I had apparently copied an old version of the shouldInteractWithUrl function from somewhere else, and could not get it to work. Finally got it working now! – Elisabeth Whiteley Jul 27 '20 at 13:37
  • pretty straight forward here! – Droid Chris Apr 26 '22 at 20:51