Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableViewCell selection Storyboard segue is slow - double tapping works though

I have a UITableViewController in a Storyboard. I have the selection of my UITableViewCell prototype trigger a segue to present another controller. The presentation itself is working.

I noticed a strange bug (possibly introduced in iOS 8) that tapping on the cell highlights the cell as expected but sometimes takes several seconds before performing the segue. Tapping on the cell twice causes the segue to happen immediately.

Has anyone else noticed this in iOS 8?

EDIT: I've now noticed that it is not just a double tap that triggers the segue faster. It is also a tap on the cell followed by a swipe anywhere. Starting to seem like a threading issue to me...

like image 879
Keller Avatar asked Oct 02 '14 16:10

Keller


2 Answers

In my case, the solution ended up being to call performSegue manually from didSelectRow on the main queue using GCD instead of using the UITableViewCell selection outlet in Storyboard.

- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  dispatch_async(dispatch_get_main_queue(), ^{
    [self performSegueWithIdentifier:kShowDetailSegue
                          sender:nil];
  });
}

I'm not sure why this became necessary- certainly you'd think that the selection outlet in Storyboard would operate on the main queue, but maybe it is an iOS 8 bug.

like image 93
Keller Avatar answered Oct 20 '22 00:10

Keller


Carlos Vela is right, the bug is accouring only when UITableViewCell selection is none and only on real device. Waking up CFRunLoop after selection solves the problem and this led me to this "universal" workaround (which is a category on UITableViewCell).

UPDATE: it works perfectly under iOS7 but under iOS8 it brokes transparent UITableViewCell background (it will be white).

#import <objc/runtime.h>

@implementation UITableViewCell (WYDoubleTapFix)

+ (void)load
{
    Method original, swizzled;

    original = class_getInstanceMethod([UITableViewCell class], @selector(setSelected:animated:));
    swizzled = class_getInstanceMethod([UITableViewCell class], @selector(mySetSelected:animated:));
    method_exchangeImplementations(original, swizzled);
}

- (void)mySetSelected:(BOOL)selected animated:(BOOL)animated
{
    [self mySetSelected:selected animated:animated];
    CFRunLoopWakeUp(CFRunLoopGetCurrent());
}

@end
like image 40
werdy Avatar answered Oct 20 '22 00:10

werdy