59

I have a UITextView which is managed via Interface Builder. As data detection I have "Links" checked. In iOS 6 everything is working fine and links are highlighted and are clickable. In iOS 7 though, all links remain just plain text. The editable and selectable checkboxes are unchecked.

What may be of concern is that the UITextView is a subview of a container view which is again inside a UIScrollView.

Tobias
  • 1,577
  • 1
  • 13
  • 20
  • http://stackoverflow.com/questions/995219/how-to-make-uitextview-detect-links-for-website-mail-and-phone-number/37745157#37745157 – Kuldeep Singh Jun 10 '16 at 09:53

17 Answers17

70

It seems that in iOS 7 link detection only works if the UITextView is selectable. So making my UITextView not selectable stopped the the link detection from working.

I also tested this in iOS 6 and I can confirm that in iOS 6 the link detection works fine even with the UITextView not being selectable.

Tobias
  • 1,577
  • 1
  • 13
  • 20
  • On iOS7.0.2 and Xcode5, when I check selectable and link on UITextView via storyboard, link detection works. However, when I set the textview on UITableViewCell on tableview, and scroll fast, it will crash saying Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'. I found out the crash won't happen when I don't check link detection on storyboard. – Umeumeume Oct 01 '13 at 05:12
  • I also found that link detection on UITextView via storyboard messes up unless I set font size programmatically. weird.. – Umeumeume Oct 01 '13 at 05:21
  • The same applies for iOS8(.1). Even worse: If I select non-editable, non-selectable and phone number detection, the app will immediately crash. Any idea how to have a phone number detection that does not allow to select the content if no phone number is detected? – Christian Nov 10 '14 at 13:50
32

I was having some problems with phone number detection today. It seemed like the UITextView would retain old phone numbers and keep text highlighted after I had set the text to something else.

I found that if I setText:nil before setting the text to the new string, it would reset the textview, and phone numbers would highlight as normal. I'm wondering if this is some kind of bug with UITextView in iOS 7.0

Either way, this did work for me.

Theo Bendixson
  • 581
  • 4
  • 12
  • 4
    Thanks for your response, but unfortunately that didn't do the trick. – Tobias Sep 24 '13 at 07:03
  • This worked for me as well. I was having trouble where the text contained both URLs and telephone numbers and the whole block of text had become one link to the phone number at the end of the text. Setting the text property to nil first resolved my issue. Thanks! – Jason Barker Feb 04 '14 at 01:47
  • 3
    Ironically I ran into this problem again in another app I'm building. Setting the textview to editable and then unsetting it to editable immediately afterward, in the prepareForReuse method seemed to work better than setting the text to nil. – Theo Bendixson Apr 29 '14 at 19:45
  • Setting the text to nil worked for me. I have a message table and when I insert messages, I check for tags in the string. If the tags are there, I use attributedText. Problem I was having is if the previous message had tags highlighted to blue, loading more messages made the other messages blue also, even if they didn't have tags. Great advice! – denikov May 15 '14 at 17:38
  • 3
    Neither setting the textView to nil nor toggling editable on and off seemed to work for me. – Trespassers W Jul 14 '14 at 07:17
  • Thank you so much man. Such a simple fix and I'm kicking myself for not thinking of it before! – IfElseTryCatch Aug 10 '15 at 20:14
26

When iOS7 first came out this plagued me and I found an answer in this thread (setting the text attribute of the UITextView to nil before setting the actual value did the trick). Then suddenly, the problem (for me it was the entire string being highlighted as a link) cropped back up (assumedly due to an iOS update).

What finally did the trick for me was to stop using the text attribute and set the attributedText. Once I did this, the need for setting fonts/scrolling/selectable/editable/etc. programmatically, disappeared. I defined my UITextView in IB, set the values as I wanted (not scrollable, not editable, selectable, detecting links and phone numbers) and then built an attributed string and set:

myUITextView.attributedString = myAttributedString;

And suddenly everything worked as expected. Hope this helps someone else down the road.

Raconteur
  • 1,381
  • 1
  • 15
  • 29
  • 2
    This is the only solution that worked for me. As of 7.0.4, none of the other solutions seemed to work any more. – aepryus Feb 20 '14 at 00:50
  • Fantastic! This is exactly what I needed - all other solutions weren't working? But this did. Thanks! – Andy Apr 06 '14 at 06:27
  • Adding my findings that this also seems to have worked for me in 7.1. Thank you very much for figuring this out. – christopherdrum Apr 07 '14 at 12:23
  • iOS 8.1 Swift, still had the same problem, textview in table cells would give linking of random pieces of text that had no link. This solved it, Thanks! – Gmeister4 Apr 02 '15 at 14:59
  • This must be considered the right answer as Missaq said it's the one without hacks – Magoo Jun 21 '15 at 19:44
  • Works for me on 8.3, however, I cannot set text color. ForegroundColor in attributed text is ignored. – Alex Sorokoletov Jul 16 '15 at 17:49
18

I had the same issue and disabling scrolling on the UITextView activates the link detection on load rather than only working once the user has interacted with the textview. The UITextView also had to be selectable and non-editable.

detailTextView.scrollEnabled = NO;
detailTextView.editable = NO;
detailTextView.selectable = YES;

Being selectable or having scroll enabled isn't necessary on iOS6.

Another thing to check is that userinteraction is enabled on the cell and content view of the cell, otherwise the link won't be clickable.

svarrall
  • 8,545
  • 2
  • 27
  • 32
16

Check These Lines must be added to use data detector property of textview in UItableView cell.

    txtvwMsgText.userInteractionEnabled = YES;
    txtvwMsgText.dataDetectorTypes = UIDataDetectorTypeLink;
    txtvwMsgText.scrollEnabled = NO;
    txtvwMsgText.editable = NO;
    txtvwMsgText.selectable = YES;
Robert
  • 5,278
  • 43
  • 65
  • 115
Harish Pathak
  • 1,567
  • 1
  • 18
  • 32
8

You should check out NSDataDetector.

You can use this to find and deal with different data (links, phone numbers and more). Have a look on this site:

http://nshipster.com/nsdatadetector/

You can also use the dataDetectorTypes property of UITextView to set what you want to detect in code. May just be a storyboard transition problem for you.

textView.dataDetectorTypes = UIDataDetectorTypeLink;
Daniel
  • 23,129
  • 12
  • 109
  • 154
  • 4
    Thank you for your answer, but in iOS 6 UITextView did this without the need for additional coding (with the right detectors set in IB). So why does that no longer work in iOS 7? – Tobias Sep 23 '13 at 15:16
  • That's why I wonder if there isn't an IB problem. Did you update to using the new storyboards in Xcode 5 maybe? – Daniel Sep 23 '13 at 15:18
  • No I used storyboards from the beginning of the project, though I updated from Xcode 4 to Xcode 5 in between. – Tobias Sep 23 '13 at 15:20
  • If you substitute the text view from your subclass to a standard one. Does it work as expected? – Daniel Sep 23 '13 at 15:56
  • No unfortunately not. I also tried to set the detector types with the code example you suggested, but to no avail. – Tobias Sep 23 '13 at 16:05
7

Be aware, that your textview will only recognize the links if not editable!

Here is a nice tutorial on how to make an editable UITextView with `link detection``

Editable UITextView with link detecion

I've not experienced any problems with that solution since now.

The trick is a GestureRecognizer forwaring touches and enabling/disabling the editing.

You could apply the same thing with the selectable / not selectable issue on iOS7

Alexander
  • 7,178
  • 8
  • 45
  • 75
6

After few tests, I found solution.

If you want links active and you don't want selection enabled, you need to edit gestureRecognizers.

For example - there are 3 LongPressGestureRecognizers. One for click on link (minimumPressDuration = 0.12), second for zoom in editable mode (minimumPressDuration = 0.5), third for selection (minimumPressDuration = 0.8). This solution removes LongPressGestureRecognizer for selecting and second for zooming in editing mode.

NSArray *textViewGestureRecognizers = self.captionTextView.gestureRecognizers;
NSMutableArray *mutableArrayOfGestureRecognizers = [[NSMutableArray alloc] init];
for (UIGestureRecognizer *gestureRecognizer in textViewGestureRecognizers) {
    if (![gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
        [mutableArrayOfGestureRecognizers addObject:gestureRecognizer];
    } else {
        UILongPressGestureRecognizer *longPressGestureRecognizer = (UILongPressGestureRecognizer *)gestureRecognizer;
        if (longPressGestureRecognizer.minimumPressDuration < 0.3) {
            [mutableArrayOfGestureRecognizers addObject:gestureRecognizer];
        }
    }
}
self.captionTextView.gestureRecognizers = mutableArrayOfGestureRecognizers;

Tested on iOS 9, but it should work on all versions (iOS 7, 8, 9). I hope it helps! :)

Jakub Kašpar
  • 228
  • 4
  • 8
4

I've found the trick, this works in iOS 7!

You have to set the UITextView selectable in your xib or programmatically

self.yourTextView.selectable = YES;

and then you have to disable scrolls and enable again after set your text.

self.yourTextView.scrollEnabled = NO;
[self.yourTextView setText:contentString];
self.yourTextView.scrollEnabled = YES;
Álvaro Murillo
  • 140
  • 1
  • 7
  • 3
    I don't know if this actually fixed the issue, or just by jamming the whatsit into the whackdoodle I fixed the thingamajigger. – Ethan Mick Feb 24 '14 at 16:21
4

So using a UITextView keeping it enabled, selectable, not scrollable & links detectable is not as simple as it seems. I encountered this in iOS 8. So my solution was to do something like this in viewDidLoad and then set editable property to NO when textBox editing is done(usually would be a method like doneIsTapped). The trick here is to set editable property to NO after setting text value to textview is completed. This will enable links in the UITextview.

- (void)viewDidLoad 
{
    [super viewDidLoad];
    self.txtViewComment.editable = YES;
    self.txtViewComment.selectable = YES;
    self.txtViewComment.dataDetectorTypes = UIDataDetectorTypeLink;
    self.txtViewComment.scrollEnabled = NO;
}

and

- (IBAction)doneIsTapped:(id)sender 
{
    self.txtViewComment.text = @"set text what ever you want";
    self.txtViewComment.editable = NO; 
}

this made the links enabled in textview. Also I would recommend not to use story board at this time(or until apple fixes this problem) and just use code to avoid any unnecessary confusion. Hope this help.

skypirate
  • 663
  • 1
  • 7
  • 13
2

Deactivating UITextViews scrolling ability did the trick for me in a similar setup.

Tharagon
  • 117
  • 4
2

Changing the Tint color to other color actually works. However if selectable enable the tint will also be the same color.

Desmond
  • 5,001
  • 14
  • 56
  • 115
  • This solved it for me. My links were working but not visible. Turns out you need to set the tint color to a proper color and it will use that for the links. Thanks Desmond. – ophychius Mar 08 '14 at 08:16
1

Make the scrolling property of UITextView to No. it will work... Self.textView.ScrollingEnable = NO;

Shaheen Rehman
  • 491
  • 1
  • 5
  • 16
1

None of the above worked for me, instead I did this:

[self.textView setDataDetectorTypes:UIDataDetectorTypeNone];
[self.textView.setTextColor:[UIColor whiteColor]];
[self.textView setDataDetectorTypes:UIDataDetectorTypeNone];

I did this with my textview that was supposed to detect all types, and which had non detected color set to white. You can change the code to represent your proper color and link types to detect.

Tunde
  • 11
  • 1
1

While this thread is old, I didn’t see an answer that worked for me with Swift, so here goes for Swift 2.2

textView.dataDetectorTypes = UIDataDetectorTypes.Link
textView.selectable = true
Silvi
  • 103
  • 5
0

This workaround works for me:

textView.selectable = YES;
textView.delegate = self;

- (void) textViewDidChangeSelection:(UITextView *)textView;
{
    NSRange range = NSMakeRange(NSNotFound, 0.0);
    if ( range.length && !NSEqualRanges(range, textView.selectedRange) ) {
        textView.selectedRange = range;
    }
}
Andrey Soloviev
  • 412
  • 3
  • 8
0

If you are adding UITextview programmatically just add below lines:

        _textView.userInteractionEnabled = YES;
        _textView.dataDetectorTypes = UIDataDetectorTypeLink;
        _textView.scrollEnabled = NO;
        _textView.editable = NO;

This worked for me.

Maishi Wadhwani
  • 1,104
  • 15
  • 24