UITextViews in a UITableView link detection bug in iOS 7

14,655

Solution 1

This appears to be a bug in iOS 7.0's UITextViews. A similar question has a workaround which seems to help: set the text view's text to nil before setting it to the new text string.

Solution 2

Several suggestions here and through links provided did not help me with this bug.

I tried setting attributed text, setting text to nil, setting text to @"".

In the end forcing the text view in an out of editable mode did the trick. In prepare for reuse

- (void)prepareForReuse
{
  ...
    textView.editable = YES;
    textView.editable = NO;
  ...
}

Solution 3

None of these answers worked for me (iOS8, Swift), the only thing that worked for me was to first set the text to nil and then prepend the new text with a non-visibile whitespace unicode character (I chose \u200B, which is the ZERO WIDTH SPACE character but any character works):

textView.text = nil
textView.text = "​\u{200B}\(newText)"

Solution 4

Found a better way to solve this problem. This requires an extra step every single time you set text. But this definitely fixes the problem.

_textView.selectable = NO; // set it to NO clears all possible data detection work so far.
_textView.selectable = YES; // set it to YES so that actual links are detected.

Basically data detection requires the selectable field to be set to YES to work. When you set it to NO, its completely removed.

Note: This is only for ios7.

Solution 5

Setting the text to nil did not work for me in a very similar problem, but setting scrollEnabled to NO, like suggested here, did the trick for me.

Edit: In addition there was still a very special case, that caused problems: When a box began with a link and the new text was set to empty text (@"" - not nil!) the box somehow "broke" and from then on any new text became a link. My solution was to override setText to set [super text] to @"x" first and then to the actual new text. Setting it to nil instead did not solve this problem either.

Share:
14,655

Related videos on Youtube

Darren
Author by

Darren

Updated on June 07, 2022

Comments

  • Darren
    Darren almost 2 years

    I have custom UITableViewCells that contain a UITextView. I have link detection in the UITextView turned on in Interface Builder. When I first load the table view, everything seems to be working, but as I scroll up and down the table view, the link detection gets messed up. Specifically, cells that just have regular text (which are presented normally initially) are being shown as links (all the text in the text view is coloured blue and is an active link), and the links point to objects that are in some of the other table view cells. For example a link might point to a website that was in a different table view cell, or launch an email to an address that was in a different table view cell.

    It seems like when the table view cells are being reused, even though the text view text is being updated, the links are somehow getting saved.

    This only happens in iOS 7, not iOS 6. It happens in the simulator and on my device.

    Here is the code:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSString *sectionKey = [self.orderedSectionKeys objectAtIndex:indexPath.section];
        NSDictionary *infoDictionary = [[self.tableViewData objectForKey:sectionKey] objectAtIndex:indexPath.row];
    
        static NSString *cellIdentifier = @"InfoDefaultTableViewCell";
        InfoDefaultTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (cell == nil) {        
            NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"InfoTableViewCells" owner:self options:nil];
            cell = [topLevelObjects objectAtIndex:0];
        }
    
        cell.bodyTextView.text = [infoDictionary objectForKey:@"description"];
    
        return cell;
    }
    

    Does anyone know what is happening here, and how to solve it?


    I tried adding this code after setting the text view text, to try to reset the links:

    cell.bodyTextView.dataDetectorTypes = UIDataDetectorTypeNone;
    cell.bodyTextView.dataDetectorTypes = UIDataDetectorTypeAddress | UIDataDetectorTypeLink | UIDataDetectorTypePhoneNumber;
    

    but it didn't change the behaviour that I'm seeing.

    • cbowns
      cbowns over 10 years
      Try printing out the text being saved into bodyTextView: it'll help show you if UITableViewCell is caching its rendered contents or if the string being retrieved isn't what you expected.
    • Darren
      Darren over 10 years
      I can log the text of the bodyTextView after I set it. It logs what I expect (the text that I set it to).
    • cbowns
      cbowns over 10 years
      Interesting. What happens when you call setNeedsDisplay on a cell that's showing the wrong string in the UI? (You can do this in the debugger to make it easy to try.)
    • Darren
      Darren over 10 years
      The correct string shows in all the table view cells. The problem is that normal strings show as links. So for example I could have the text: "This is my text." and it will be in a blue font colour and link to, for example, a website that is written in the text view of another table view cell.
    • cbowns
      cbowns over 10 years
      Oh, I see. Sorry, I misread earlier. It sounds like a UIKit bug. Have you tried manually setting/resetting properties surrounding link detection properties on the text view after setting the new text? (in an effort to have it re-parse and render its contents)
    • Darren
      Darren over 10 years
      Yes I did try that, no luck. I'll add what I did to my question. I think that it is a UIKit bug, I hope I can find a way to get around it though until it's fixed.
    • cbowns
      cbowns over 10 years
      Gotcha. I just found this answer on another related thread which sounds helpful? stackoverflow.com/a/18968687/774
    • Darren
      Darren over 10 years
      Excellent, it worked! I had seen that question, but I hadn't seen that answer. Thanks!!
    • scrrr
      scrrr about 10 years
      Use AttributedStrings for your textView. See [this StackOverflow answer][1]. [1]: stackoverflow.com/a/20669356/340354
    • mrmichaeldev
      mrmichaeldev about 10 years
      I've answered this question here. stackoverflow.com/a/22457773/821690
  • nekno
    nekno over 10 years
    Yes, def filing a bug.
  • SAHM
    SAHM over 10 years
    how do you set [super text]?
  • SAHM
    SAHM over 10 years
    I figured it out, subclass UITextView, and I have not tested thoroughly yet, but it seems to be working for me
  • alexdd55
    alexdd55 over 10 years
    seems to be a bug, but setting text to nil, didn't do it for me :(
  • cbowns
    cbowns over 10 years
    @BioCho on what iOS version?
  • cbowns
    cbowns over 10 years
    @BioCho It sounds like Theragon's answer may be helpful (stackoverflow.com/a/19589680/774)
  • TalkLittle
    TalkLittle about 10 years
    This works. Found this was resetting textColor instead of improperly adding link, so had to reset textColor too. Unfortunately Instruments is telling me that all these steps combined are even slower than using setAttributedText:, on iPod Touch iOS 7.1.
  • Ethan
    Ethan almost 10 years
    This is the only solution that works (besides the solutions involving creating a new UITextView each time, which I don't want to do for performance reasons)
  • villapossu
    villapossu over 9 years
    I'm still seeing this bug in iOS 8. Argh.
  • cbowns
    cbowns over 9 years
    Not surprising: I don't see anyone that's affected by this talking about filing a bug with a test case.
  • nacross
    nacross over 9 years
    This worked for me, but only when I also set the attributedText to nil before updating the text property.
  • Michał Zygar
    Michał Zygar over 9 years
    this seems to be a proper fix. When you enable data detection, they get separate attributes from the plain text, thus the whole text become NSAttributedString.
  • Andrei Konstantinov
    Andrei Konstantinov over 9 years
    Works for me too. Awesome! Do you have any explanation why it works this way?
  • Phamer
    Phamer almost 9 years
    Worked for me using Objective C: textView.text = [@"\u200B" stringByAppendingString:message.content];
  • jose920405
    jose920405 almost 9 years
    This works, but cause wrong functionallity in gestures
  • jose920405
    jose920405 almost 9 years
    This is causing a strange blink in the text
  • rptwsthi
    rptwsthi almost 9 years
    @melvinmt how did you came up with this solutions, that bugs me? This is like most ridiculous solution but it works.
  • rptwsthi
    rptwsthi almost 9 years
    you must manage removing descriptionTV (if you are reusing your table view cell, and you should reuse your table view cell).
  • rishiAgar
    rishiAgar over 8 years
    Cannot understand why it fixed the problem, but works like a charm.