iOS 17 crash with presenting modal view controller on itself using deprecated keyWindow

329 views Asked by At

Since the upgrade from iOS 15 to iOS 17, my iPad app has been crashing when I try to display modal popovers with the following error and I am unable to resolve the issue:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modal view controller on itself. Presenting controller is <VolumeVC: 0x7fc81882c520>.'

For context, I've been using the following utility class throughout my app to first get the top most view controller in the window so that I can then display a modal popover with a view controller in it.

Utility.m

+ (UIViewController*)topViewController {
        
    UIViewController *topVC = [[UIApplication sharedApplication] keyWindow].rootViewController;
    NSLog(@"Utility::topViewController(): topVC is: %@", topVC);
    
    int countLoops = 0;
    while (topVC.presentedViewController != nil) {
        topVC = topVC.presentedViewController;
        NSLog(@"Utility::topViewController(): In loop, topVC is: %@, countLoops is: %i", topVC, countLoops);
        countLoops++;
        if (countLoops > 25) { break; }
    } 
    return topVC;
}

+ (void)showDialogiPad:(UIViewController *)contentVC
       fromPresentingVC:(UIViewController *)presentingVC
                 inView:(UIView *)view
                atFrame:(CGRect)frame
          withDirection:(UIPopoverArrowDirection)direction {
    
    // Choose the presentation style in which the content is displayed in a popover view
    contentVC.modalPresentationStyle = UIModalPresentationPopover;
    
    // Set the popover size, anchor location and direction
    contentVC.popoverPresentationController.sourceRect = frame;
    contentVC.popoverPresentationController.sourceView = view;
    contentVC.popoverPresentationController.permittedArrowDirections = direction;
   
    // Set the arrow direction for the popover
    popoverVC.permittedArrowDirections = direction;
    
    // Present the popover presentation controller
    [presentingVC presentViewController:contentVC animated:YES completion:nil];
}

An example of how this gets called from elsewhere in the code is the following:

    // Show the volume view controller in a popover
    [Utility showDialogiPad:volumeVC // volumeVC is a simple view controller I want to show in the popup
        fromPresentingVC:[Utility topViewController]
                  inView:view
                 atFrame:frame
           withDirection:UIPopoverArrowDirectionAny];

A few notes:

  • This code will work 1 to N times of opening & closing the popover but it will always eventually crash as of iOS 17. The crash always seems to happen when I open and close the popover quickly in succession.
  • frame and view are always populated with the correct values, and volumeVC and presentingVC are always non-nil when I print them out in the Utility::showDialogiPad dialog method.
  • When it crashes, the output of the debug statements in + (UIViewController*)topViewController are:
Utility::topViewController(): topVC is: <UITabBarController: 0x7fc22d81ae00>
Utility::topViewController(): In loop, topVC is: <VolumeVC: 0x7fc22d01f460>, countLoops is: 0
  • The main window of the app is a UITabBarController with a UISplitViewController in each tab.
  • This app does not have multiple scenes in it nor does it use UIWindowScene.
  • I know keyWindow is deprecated as of iOS 13. When I replace the topViewController code with the following:
+ (UIViewController*)topViewController {
    UIWindowScene *windowScene = (UIWindowScene *)[UIApplication sharedApplication].connectedScenes.allObjects.firstObject;
    UIViewController *topVC = windowScene.windows.firstObject.rootViewController;    
    return topVC;
}

It will work 1 to N times but eventually it will crash with this error:

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'UIPopoverPresentationController (<UIPopoverPresentationController: 0x7ff05c156890>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.'

Thanks for any assistance with this.

0

There are 0 answers