112

I just came across a crash showing a NSInvalidArgumentException with this message on an app which wasn't doing this before.

Application tried to present modally an active controller UITabBarController: 0x83d7f00.

I have a UITabBarController which I create in the AppDelegate and give it the array of UIViewControllers.

One of them I want to present modally when tapped on it. I did that by implementing the delegate method

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController

If that view controller is of the class of the one I want to present modally, I return NO and do

[tabBarController presentModalViewController:viewController animated:YES];

And now I'm getting that error, which seems to mean that you can't present modally a view controller that is active somewhere else (in the tabbar...) I should say I'm on XCode 4.2 Developer Preview 7, so this is iOS 5 (I know about the NDA, but I think I'm not giving any forbidden details). I currently don't have an XCode installation to test if this crashes compiling against the iOS4 SDK, but I'm almost entirely sure it doesn't.

I only wanted to ask if anyone has experienced this issue or has any suggestion

Javier Soto
  • 4,840
  • 4
  • 26
  • 46
  • Prior to iOS 5, this did not raise an exception, but returned nothing. From iOS 5 on, this command raises an exception. – Frederic Adda Aug 18 '12 at 22:17

11 Answers11

107

Assume you have three view controllers instantiated like so:

UIViewController* vc1 = [[UIViewController alloc] init];
UIViewController* vc2 = [[UIViewController alloc] init];
UIViewController* vc3 = [[UIViewController alloc] init];

You have added them to a tab bar like this:

UITabBarController* tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:[NSArray arrayWithObjects:vc1, vc2, vc3, nil]];

Now you are trying to do something like this:

[tabBarController presentModalViewController:vc3];

This will give you an error because that Tab Bar Controller has a death grip on the view controller that you gave it. You can either not add it to the array of view controllers on the tab bar, or you can not present it modally.

Apple expects you to treat their UI elements in a certain way. This is probably buried in the Human Interface Guidelines somewhere as a "don't do this because we aren't expecting you to ever want to do this".

lswank
  • 2,471
  • 1
  • 24
  • 21
  • 6
    The thing is this was absolutely no problem prior to iOS 5, hence my concern! What I did was to add a dummy UIViewController to the tabbar and present modally the actual view controller subclass instance. – Javier Soto Sep 25 '11 at 18:00
  • 1
    @Iswank, now in iOS 6, to make things "easier," they deprecated presentModalViewController causing all kinds of rotational problems...you need to use presentViewController: animated: completion and check how your app is handling the changes – whyoz Mar 12 '13 at 17:56
  • what if need to present exactly from "selected controller"? I mean to leave tabor visible – Gargo Feb 27 '23 at 12:10
16

In my case i was trying to present the viewController (i have the reference of the viewController in the TabBarViewController) from different view controllers and it was crashing with the above message. In that case to avoid presenting you can use

viewController.isBeingPresented

!viewController.isBeingPresented {
          // Present your ViewController only if its not present to the user currently.
}

Might help someone.

Karthick Ramesh
  • 1,451
  • 20
  • 30
  • it is working only in viewWillappperar but when i have check it before presenting viewController which is already presented, it is always return false. – guru Aug 08 '18 at 07:24
  • 2
    Not working for me. Still gets app crash. (!viewController.presentingViewController) resolved problem. – Argus Sep 25 '18 at 13:40
16

I have the same problem. I try to present view controller just after dismissing.

[self dismissModalViewControllerAnimated:YES];

When I try to do it without animation it works perfectly so the problem is that controller is still alive. I think that the best solution is to use dismissViewControllerAnimated:completion: for iOS5

Danil
  • 1,780
  • 17
  • 24
7

The same problem error happened to me when I tried to present a child view controller instead of its UINavigationViewController parent

Nik
  • 9,063
  • 7
  • 66
  • 81
4

I had same problem.I solve it. You can try This code:

[tabBarController setSelectedIndex:1];
[self dismissModalViewControllerAnimated:YES];
Erhan Demirci
  • 4,173
  • 4
  • 36
  • 44
3

For React Native Developer - Problem might not be in AppDelegate Or main.m if app has been successfully build and is running and will crash after splash or perhaps the error screen

Issue might be due to use of fonts/resources that is not available with xcode and not properly configured.. You can find out the error by commenting certain portion starting from App.js and drilling inside the navigation/screens and commenting the components till you find the component that is generating the error....

In my case the resource of fontFamily was making an issue which was used right after splash in walkthrough screen

<Text style={{fontFamily: Fonts.roboto}}>ABC</Text>

Here font roboto wasnot configured properly. Wasted entire days just debugging the error hope its helps you

Rahul Shakya
  • 1,269
  • 15
  • 15
1

In my case, I was presenting the rootViewController of an UINavigationController when I was supposed to present the UINavigationController itself.

Laura Corssac
  • 1,217
  • 1
  • 13
  • 23
1

For React Native developers: answer give by @rahul-shakya was not the reason for my.

We were using react-native-loading-spinner-overlay (we will call it Spinner) to show the progress bar, which internally uses Modal when we were transitioning from one screen to another we were not hiding the Spinner that lead to this issue.

Just hiding the Spinner & giving some delay before navigation it worked.

So in general if our code is trying to show one modal over other then we get into such issues, in react-native it is quite hard to find as we will have to see the lib code to understand if that is using modal.

Gokul Kulkarni
  • 2,069
  • 3
  • 26
  • 42
0

Instead of using:

self.present(viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Void)?)

you can use:

self.navigationController?.pushViewController(viewController: UIViewController, animated: Bool)
aturan23
  • 4,798
  • 4
  • 28
  • 52
Wimukthi Rajapaksha
  • 961
  • 1
  • 11
  • 23
0

This is my way which supporting multiple Windows(from a single APP) on the iPad and nested modal present.

import UIKit

///✅Use this public method
public func SheetViewController(ViewController:UIViewController) {
    
    for i in returnAvailableViewControllers().shuffled() {
        if i.presentedViewController == nil && !ViewController.isViewLoaded {i.present(ViewController, animated: true, completion:  {})}
    }
}

///Returns all possible ViewControllers
private func returnAvailableViewControllers() -> [UIViewController] {
    let 场景 = UIApplication.shared.connectedScenes
    
    var 存储VC : [UIViewController] = []

    for i in 场景 {
        
        if i.activationState == .foregroundActive {
            //⭐️Set up “foregroundActive” to give the user more control
            var 视图控制器 = (i.delegate as? UIWindowSceneDelegate)?.window??.rootViewController
            
            if 视图控制器 != nil {
                存储VC.append(视图控制器!)
            }
            
            
            
            var 结束没 = true
            while 结束没 {
                //Enumerate all child ViewController
                视图控制器 = 视图控制器?.presentedViewController
                if 视图控制器 != nil {
                    存储VC.append(视图控制器!)
                } else {
                    结束没.toggle()
                }
            }
        }
        
        
    }
    return 存储VC
}
闪电狮
  • 367
  • 2
  • 9
0

Just remove

[tabBarController presentModalViewController:viewController animated:YES];

and keep

[self dismissModalViewControllerAnimated:YES];
user170317
  • 1,152
  • 2
  • 11
  • 22