Search code examples
iosuitableviewios7segueuistoryboardsegue

iOS7 issue with modal view controller segue from custom cell selection


Final Edit

After further investigation I thought it would be best to repost the question with more information on the sepcific issue.

This issue seems to occur only on iOS7. I have tested on iOS6 and this works without issue.

-- Setup The setup is you have one UIViewController (first VC for example), this holds a tableView and is the datasource/delegate. When the cell in tableView is selected/tapped you perform a segue to the Second View Controller (this can be empty for now).

Issue

The issue is that the segue does not occur immediately. Within a second as expected. There is no data being passed in the segue or anything being loaded in the second view controller so you expect it to be instant.

Sometimes, this will work fine without any issues. Other times, you will click the cell and nothing will happen.

--Noticed Trend What I have noticed is that when the 'issue' occurs. The simulator/device will wait until the next minute begins then force through the load of the modal view controller. OR When the issue occurs you can click/tap again anywhere on the device screen to 'force' the load through.

The issue can be reproduced in a new project just with the basics in. I have uploaded a sample project zip that includes this.

Additional Code (if needed)

I have a custom cell setup. When the cell is selected I perform the following:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"%s",__PRETTY_FUNCTION__);

    if (indexPath.section == 0) {
        [self performSegueWithIdentifier:@"selectGameTurnDiff" sender:self];
    } 
}

I then have the following in the prepareForSegue:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    NSLog(@"%s",__PRETTY_FUNCTION__);
    [super prepareForSegue:segue sender:sender];
}

Logging

Here are some example logs to show this: Run 1
2013-10-09 23:54:09.855 App[14954:a0b] -[FirstViewController tableView:didSelectRowAtIndexPath:]
2013-10-09 23:54:09.857 App[14954:a0b] -[FirstViewController prepareForSegue:sender:]
2013-10-09 23:55:00.004 App[14954:a0b] -[SecondViewController viewDidLoad]
2013-10-09 23:55:00.004 App[14954:a0b] -[SecondViewController viewWillAppear:]
2013-10-09 23:55:00.511 App[14954:a0b] -[SecondViewController viewDidAppear:]

Run 2
2013-10-09 23:56:21.900 App[14954:a0b] -[FirstViewController tableView:didSelectRowAtIndexPath:]
2013-10-09 23:56:21.901 App[14954:a0b] -[FirstViewController prepareForSegue:sender:]
2013-10-09 23:57:00.003 App[14954:a0b] -[SecondViewController viewDidLoad]
2013-10-09 23:57:00.003 App[14954:a0b] -[SecondViewController viewWillAppear:]
2013-10-09 23:57:00.508 App[14954:a0b] -[SecondViewController viewDidAppear:]

Run 3
2013-10-09 23:57:43.387 App[14954:a0b] -[FirstViewController tableView:didSelectRowAtIndexPath:]
2013-10-09 23:57:43.388 App[14954:a0b] -[FirstViewController prepareForSegue:sender:]
2013-10-09 23:58:00.004 App[14954:a0b] -[SecondViewController viewDidLoad]
2013-10-09 23:58:00.004 App[14954:a0b] -[SecondViewController viewWillAppear:]
2013-10-09 23:58:00.510 App[14954:a0b] -[SecondViewController viewDidAppear:]


Solution

  • After filling a Radar Apple responded with adding:

    dispatch_async(dispatch_get_main_queue(), ^{});
    

    To the end of the following method, which does the trick:

    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    

    In the method that presents the controller, you can schedule a no-op block which will force the runloop to spin and there will be no delay.

    Radar Ref: 15196237, feel free to file another and reference this.