Uitextviews in a Uitableview Link Detection Bug in iOS 7

UITextViews in a UITableView link detection bug in iOS 7

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.

iOS 7 UITextView link detection crash in UITableView

The crash happens when two cells with data type are being dequeued while
using the same cell identifier.
It seems to be a bug in iOS, but Apple may have good reasons to implement it this way.
(memory wise)

And so the only 100% bullet proof solution is to provide a unique identifier for cells
containing data types.
This doesn't mean you will set a unique identifier to all cells in your table, of course,
as it will eat up too much memory and your table scroll will be really slow.

You can use NSDataDetector to determine if a matched type was found on your text,
and only then save the found object as the cell identifier, like so:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

NSString *row = [self.dataSource objectAtIndex:indexPath.row];
static NSDataDetector *detector = nil;
if (!detector)
{
NSError *error = NULL;
detector = [[NSDataDetector alloc] initWithTypes:NSTextCheckingTypeLink | NSTextCheckingTypePhoneNumber error:&error];
}

NSTextCheckingResult *firstDataType = [detector firstMatchInString:row
options:0
range:NSMakeRange(0, [row length])];
NSString *dataTypeIdentifier = @"0";
if (firstDataType)
{
if (firstDataType.resultType == NSTextCheckingTypeLink)
dataTypeIdentifier = [(NSURL *)[firstDataType URL] absoluteString];
else if (firstDataType.resultType == NSTextCheckingTypePhoneNumber)
dataTypeIdentifier = [firstDataType phoneNumber];
}

NSString *CellIdentifier = [NSString stringWithFormat:@"Cell_%@", dataTypeIdentifier];

UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
...

Note: Initializing NSDataDetector *detector as static
rather than initialize it for each cell improves performance.

UITextView link detection in iOS 7

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.

Link detection in a UITextView inside a UITableViewCell - iOS 7

try again after increase row height of a cell in [tableView:heightForRowAtIndexPath].

If it works, you need to change of height of cell dynamically.

UITextView: Link detection working within Simulator, not on device

It appears that the trick is to setScrollable:NO. Seems to fix the problem, although if you need scrolling, I'm not sure what the answer will be...

UITextView hyperlink formatting/function remains even after text changed to text without any links

From this previous answer, UITextViews in a UITableView link detection bug in iOS 7, it appears this was something of a bug in ios 7. The solutions there did not work for me, but what did work for me was creating a new UITextView for each set of text, since the first set of text was always fine. If someone has a reason (other than bug) for why this might be happening, I would love to know since I still cannot update or reset a UITextView without having this bug.

UITableView in iOS 7 not scrolling to correct location when editing UITextView in cell

Try to adjust UITableView frame when keyboard appears. Call [self attachKeyboardHelper] in viewWillAppear and [self detachKeyboardHelper] in viewWillDisappear.

- (void)attachKeyboardHelper{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillAppear:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}

- (void)detachKeyboardHelper{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)keyboardWillAppear:(NSNotification *)notification{
NSDictionary* userInfo = [notification userInfo];

NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;

[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];

// Animate up or down
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];

CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
if(self.view==self.tableView){
CGRect newTableFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.view.bounds.size.height-keyboardFrame.size.height);
self.tableView.frame = newTableFrame;
}else{
CGRect newTableFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.view.bounds.size.height-self.tableView.frame.origin.y-keyboardFrame.size.height);
self.tableView.frame = newTableFrame;
}

[UIView commitAnimations];
}

- (void)keyboardWillHide:(NSNotification *)notification{
NSDictionary* userInfo = [notification userInfo];

NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;

[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];

CGRect newTableFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.view.superview.bounds.size.height-self.tableView.frame.origin.y);
self.tableView.frame = newTableFrame;
if(newTableFrame.size.height>self.tableView.contentSize.height-self.tableView.contentOffset.y){
float newOffset=MAX(self.tableView.contentSize.height-newTableFrame.size.height, 0);
[self.tableView setContentOffset:CGPointMake(0, newOffset) animated:YES];
}

}


Related Topics



Leave a reply



Submit