23
votes

Compiling and running using iOS 7 - I am getting warning message: "Presenting view controllers on detached view controllers is discouraged" while presenting modal view controller. I never had problem with iOS 6 or earlier version. Can anyone show if anything changed while presenting the modal view controller?

SearchViewController *controller1;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
    controller1 = [[SearchViewController alloc] initWithNibName:@"SearchViewController-iPad" bundle:nil];
}
else
{
   controller1 = [[SearchViewController alloc] initWithNibName:@"SearchViewController" bundle:nil];
}
controller1.delegate = self;
[[self navigationController] presentModalViewController:controller1 animated:YES];

*EDIT * Here is the code Can someone point out where it is nested. Looks like they are nested, Please suggest how to link using child viewcontroller pattern.

(void)applicationDidFinishLaunching:(UIApplication *)application
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
    {
        self.loginRootviewController =   [[MainViewController alloc] initWithNibName:@"MainViewController-iPad" bundle:nil];
    }
    else
    {
       self.loginRootviewController =   [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
    }

    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.loginRootviewController];


    DDMenuController *rootController = [[DDMenuController alloc] initWithRootViewController:navController];
    _menuController = rootController;



    AppMainMenuViewController *leftController = [[AppMainMenuViewController alloc] init];
    rootController.leftViewController = leftController;
    self.loginRootviewController.delegateLogin = leftController;

    self.window.rootViewController = rootController;

    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

}
11
BTW, presentModalViewController:animated: is depreciated, you should use the new method.rdelmar
presentModalViewController:animated: is deprecated since iOS 6.0 use presentViewController:animated:completion: instead.Sviatoslav Yakymiv
Do not present from navigation controller, instead present from "self". UIKit handles this and will find who's the best candidate to be presenting VC.Ben Affleck

11 Answers

18
votes

A view controller is detached if the story board is not aware of any segues that connect that view controller in any way back to the root view controller.

It's suggested that you create a segue via Interface Builder and call it in code, even for a modal view, if you are using a storyboard.

Even with XCode 4.6.x and iOS 6.x, you got warnings at build time about unattached view controllers.

If you have two storyboards (one for iPhone and one for iPad), you can name the segue the same for each. Segue identifiers only have to be unique per storyboard. So, performing a segue (performSegueWithIdentifier) with the same identifier can take you to one place on the iPhone and another on the iPad.

18
votes

I had the same problem, and me too I was NOT using storyboard (I am working on a three years old project).

In my case the cause was that I did not assign the rootViewController of my application to the window, like this:

- (BOOL)application:didFinishLaunchingWithOptions:
{
    ...
    self.window.rootViewController = myRootViewController; // I was missing this
    ...
}

No more warnings now.

18
votes

This warning normally comes when we try to present a view controller modally in other view controller which is not part of rootViewController, and we just addSubview the view controller's view.

At this stage we should call presentViewController in that view controller which is part of rootViewController.

So we can directly present any view controller in rootViewController

UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
[vc presentViewController:obj animated:YES completion:nil];
[vc dismissViewControllerAnimated:YES completion:nil];
7
votes

For those using DDMenuViewController, this is an easy fix. Just add [self addChildViewController:controller]; to initWithRootViewController, and to setRightViewController and setLeftViewController.

4
votes

To avoid getting the warning in a push navigation, you can directly use :

[self.view.window.rootViewController presentViewController:viewController animated:YES completion:nil];

And then in your modal view controller, when everything is finished, you can just call :

[self dismissViewControllerAnimated:YES completion:nil];

2
votes

This message still may appear when you have nested viewcontrollers. If that is the case, make sure they are linked using the child viewcontroller pattern.

2
votes

If you are using storyboard and get this error, it can happen when trying to automatically present a view from viewDidLoad too quickly. If you call your modal segue after a small amount of time it works without any further warnings.

1
votes

Calling [self presentViewController:vc animated:NO completion:nil]; in viewDidAppear fixed the issue for me.

0
votes

I had the same problem. But rather than it being how I started the view, it was how the view was configured. I had accidentally set the class on the view to the view controller class instead of on the files owner. The clue was that it displayed the view, but some of the styling was missing. The weird thing is that it was working on older versions of iOS.

0
votes

I found that, if you are using a storyboard, you will want to put the code that is presenting the new view controller in viewDidAppear. It will also get rid of the "Unbalanced calls to begin/end appearance transitions for..." warning.

-5
votes

Under iOS 7, presentModalViewController is deprecated.

I've replaced it with

[self.navigationController pushViewController: View animated: YES ];

and it fixed a number of errors I was getting.

Worth a try.