0

I have following text in the app integrated within UITextView

By using this application, you agree to our User Agreement and Privacy Policy.

What I want to achieve is to have separate clicks recognized for both bolded sections clicked that are going to open SafariViewController. What I need is something like link recognition where I can put text

By using this application, you agree to our User Agreement(link:@"https://google.com/agreement") and Privacy Policy(link:@"https://google.com/privacy").

I want this text to be shown as the one above, and on click of a textView that it opens these "hidden" links. Is this possible? I've found a solution where a guy creates N number of UILabels (each label is 1 character), attaching gesture recognizers on underlined text. I hate this solution since it is more a hack than a solution when iOS provides you with TextView already that supports linking text.

EDIT:

Found a working solution after few suggestions below and some adjustments...

  1. You need to create UITextView in which you will create your linked text

  2. Create text attributes for normal text, and for text marked as links

    NSDictionary *orangeTextAttributes = @{NSForegroundColorAttributeName: [UIColor orangeColor], NSFontAttributeName: [UIFont systemFontOfSize:14 weight:UIFontWeightThin], NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)};
    NSDictionary *normalTextAttributes = @{NSForegroundColorAttributeName: [UIColor blackColor], NSFontAttributeName: [UIFont systemFontOfSize:14 weight:UIFontWeightThin]};
    
  3. Use that attributes to the text

    NSMutableAttributedString *labelAttributedText = [[NSMutableAttributedString alloc] initWithString:@"By using this application, you agree to Google's User Agreement and Privacy Policy." attributes:normalTextAttributes];
    [self addLink:@"https://google.com/terms-of-services" toString:@"User Agreement" ofAttributedString:labelAttributedText];
    [self addLink:@"https://google.com/privacy" toString:@"Privacy Policy" ofAttributedString:labelAttributedText];
    
    self.termsAndPolicyTextView.linkTextAttributes = orangeTextAttributes;
    self.termsAndPolicyTextView.attributedText = labelAttributedText;
    
  4. Add method to attach links to your TextView text

    - (void)addLink:(NSString *)urlString toString:(NSString *)substringToBeLinked ofAttributedString:(NSMutableAttributedString *)entireAttributedString {
        NSRange substringRange = [[entireAttributedString string] rangeOfString:substringToBeLinked];
        if (substringRange.location != NSNotFound) {
            [entireAttributedString addAttribute:NSLinkAttributeName value:urlString range:substringRange];
        }
    }
    
  5. Attack delegate to your text view, and handle callback in which link click is registered

    - (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction {
        //This is where you open your link in browser for example
        return NO;
    }
    
Aleksandar
  • 1,457
  • 13
  • 30
  • 4
    Use `NSAttributedString` and the `UITextViewDelegate` corresponding to handle the touch on links. – Larme Mar 22 '18 at 13:42
  • I don't have links, I just have words. Need to verify if location of a touch is in range of a "desired string". – Aleksandar Mar 22 '18 at 13:45
  • 3
    That's exactly what `NSAttributedString` does. Refer https://stackoverflow.com/questions/21629784/how-to-make-a-clickable-link-in-an-nsattributedstring-for-a – Rishab Mar 22 '18 at 13:48
  • 1
    Another link (no pun) that could help to detect a tap on a word: https://stackoverflow.com/questions/11349459/get-word-from-long-tap-in-a-word-of-uitextview – koen Mar 22 '18 at 13:49
  • 1
    "User Agreement(link:@"https://google.com/agreement") " That's what would do a NSAttributedString correctly set. It will embed the link under "User Agreement", converting it to a "clickable word" in other words... – Larme Mar 22 '18 at 13:51
  • Can this be done with UILabel or it has to be UITextView? – Aleksandar Mar 22 '18 at 13:58
  • NSAttributedString can be used on UILabel or UITextView. But UITextView provides handler for the tap on links. At some point you need to look yourself for "NSAttributedString + Link", then "UITextView + Link". – Larme Mar 22 '18 at 14:06
  • Found a working solution with UITextView and linking. Works perfectly for my needs. Made also some localization tweaks to be as configurable as it gets. Posted simple edit above to show how it is done... – Aleksandar Mar 23 '18 at 09:22

1 Answers1

0

Maybe, you should use UITextView. If you use UITextView you will be able to do something like this:

  @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 - Yahoo"
        let linkString = NSMutableAttributedString(string: string)
        linkString.addAttribute(NSLinkAttributeName, value: NSURL(string: "https://www.google.com")!, range: NSMakeRange(0, 5))
        linkString.addAttribute(NSFontAttributeName, value: UIFont(name: "HelveticaNeue", size: 25.0)!, range: NSMakeRange(0, 5))
        linkString.addAttribute(NSLinkAttributeName, value: NSURL(string: "https://www.yahoo.com")!, range: NSMakeRange(9, string.characters.count))
        linkString.addAttribute(NSFontAttributeName, value: UIFont(name: "HelveticaNeue", size: 25.0)!, range: NSMakeRange(9, string.characters.count))
        textView.attributedText = linkString
        textView.delegate = self
        textView.selectable = true
        textView.userInteractionEnabled = true
  }

Also, remeber implement the delegate methods:

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

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

The last thing that you need to pay attention is the UITextView configuration on IB:

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