title: App delegate check when all view controller transitions finished
body: <p>I would like my app to be able to respond to remote push delivered to my device. What I would like to do is to present a view controller as a response to a push notification.</p>
  
  <p>When the app is running there is no problem with doing so. From the app delegate I start by getting the root view controller and going all the way up so that I find the visible view controller and present a new one over it. Works like charm.</p>
  
  <p>When the app is launched however I first show the root view controller which then checks if any cached data is stored on the device and if so it loads up a new view controller which presents it. Sometimes it takes 2s and sometimes it takes let's say 7s. There is no way of telling how long the operations are going to take when the app is all done presenting new view controllers. So the situation gets tricky if I want to present a view controller right after launch.</p>
  
  <p>Currently I'm using a hacky version which relies on <code>dispatch_after</code> snippet which triggers the presentation around 5s after the app launch. It works in 95% of the cases but I don't like the solution.</p>
  
  <p>So my question is: how can I get notified in <code>appDelegate</code> when all the modal transitions have completed and my app is in a "stable final" (such that I can get the topmost view controller and present over it with no harm) state?</p>
  
  <p>I can paste some code that I'm already using if that would help in any way.</p>
  
  <p><strong>EDIT</strong><br>
  I was asked to paste some code how I'm presenting view controllers from app delegate. The snippet below gets called when the <code>application:didFinishLaunchingWithOptions:</code> is called and there is a <code>UIApplicationLaunchOptionsRemoteNotificationKey</code> entry in the <code>launchOptions</code> dictionary.</p>
  
  <pre><code>dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      UIViewController *controller = [self topViewControllerFromController:self.window.rootViewController];
      NSInteger messageID = [userInfo[@"m_id"] integerValue];
  
      MessageViewController *mvc = [[MessageViewController alloc] initWithMessageID:messageID];
      mvc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
  
      [controller presentViewController:mvc animated:YES completion:nil];
  });
  </code></pre>
  
  <p>and the <code>topViewController</code> is pretty straightforward:</p>
  
  <pre><code>- (UIViewController *)topViewControllerFromController:(UIViewController *)controller
  {
      if (controller.presentedViewController)
      {
          UIViewController *presentedViewController = controller.presentedViewController;
          return [self topViewControllerFromController:presentedViewController];
      }
      else if ([controller isKindOfClass:[UINavigationController class]])
      {
          UINavigationController *navigationController = (UINavigationController *)controller;
          return [self topViewControllerFromController:navigationController.visibleViewController];
      }
      else if ([controller isKindOfClass:[UITabBarController class]])
      {
          UITabBarController *tabBarController = (UITabBarController *)controller;
          return [self topViewControllerFromController:tabBarController.selectedViewController];
      }
      else
      {
          return controller;
      }
  }
  </code></pre>
  
  <p>Now the presentation and stuff works as it should and there is no problem with it. I only need to know when all the modal transitions are done ie. when the app is good to present another one.</p>