Search code examples
iosobjective-csegueuistoryboardsegue

How to perform segue after current presentation is completed


I have a situation in my app where I need to dismiss a modal view controller via unwind segue, then right after that present a different modal view controller. To do so, I am simply delaying the call to present the new view controller by 1.0 seconds. This may not work all the time, perhaps if it takes longer to dismiss for some reason, the second view controller won't be able to appear because a transition is occurring. I just ran into this situation, although it did work in this case. This was logged:

Warning: Attempt to present on while a presentation is in progress!

I am looking for a better solution. I wondered if it would be possible to throw up the new view controller after the first one is fully dismissed, via a callback, but there is no performSegueWithIdentifier that has a completion block.

How can I dismiss a modal view controller then present a new one afterwards, always ensuring there will be no conflict?

This is my current solution:

[self performSegueWithIdentifier:@"Unwind Segue" sender:self]; //dismiss modal or pushed VC

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [tabBarController performSegueWithIdentifier:@"Show New VC" sender:self]; //present new modal VC
});

Solution

  • What you can also do is add a notification on the new controller's viewDidAppear function using NSNotificationCenter. Then, you attach a listener to the notification and when you see the notification show up, you do your next transition.

    - (void)viewDidLoad {
        [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"transitioned to new controller!" object:nil]];
    }
    

    elsewhere, just add this to listen to the notification.

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedNotification:) name:@"transitioned to new controller!" object:nil];
    

    Don't forget to stop listening after you receive your notification (unless you desire to remain observing) for this notification, otherwise you will continue observing all notifications throughout your application:

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"transitioned to new controller!" object:nil];