Rectangle 27 29

You can't display a modal view controller from the appDelegate. You need to display a modal ViewController from whichever viewController is currently displaying full-screen. In other words, you need to put that code into your root view controller, or whichever one you want to display the modal vc from...

Also, you'll want to use the method "presentModalViewController" to present the modal. You can set properties on the modal vc such as:

vC.modalPresentationStyle = UIModalPresentationFormSheet;
vC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:vC animated:YES];

but the rootViewController isn't the one displayed at the moment? How should I implement generic function, that whenever user credentials check fails it can present a login view controller?

Are you using a navigation controller?

I would use a navigation controller and then you can get a reference to the displayed one like: displayedController = [navController topViewController]; Then you can push modally like above where you would replace self with displayedController.

I fixed this problem by taking out the present method of the viewDidLoad and put it in the viewDidAppear.

This solution is outdated: 'presentModalViewController:animated:' is deprecated: first deprecated in iOS 6.0.

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 29

You can't display a modal view controller from the appDelegate. You need to display a modal ViewController from whichever viewController is currently displaying full-screen. In other words, you need to put that code into your root view controller, or whichever one you want to display the modal vc from...

Also, you'll want to use the method "presentModalViewController" to present the modal. You can set properties on the modal vc such as:

vC.modalPresentationStyle = UIModalPresentationFormSheet;
vC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:vC animated:YES];

but the rootViewController isn't the one displayed at the moment? How should I implement generic function, that whenever user credentials check fails it can present a login view controller?

Are you using a navigation controller?

I would use a navigation controller and then you can get a reference to the displayed one like: displayedController = [navController topViewController]; Then you can push modally like above where you would replace self with displayedController.

I fixed this problem by taking out the present method of the viewDidLoad and put it in the viewDidAppear.

This solution is outdated: 'presentModalViewController:animated:' is deprecated: first deprecated in iOS 6.0.

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 19

You can actually present a modal view Controller from the AppDelegate as long as you detect the current visible viewController and take care of the case where you current controller is a navigationController.

Here is what I do:

UIViewController *activeController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
   activeController = [(UINavigationController*) activeController visibleViewController];
}
[activeController presentModalViewController:loginViewController animated:YES];
[activeController presentModalViewController:loginViewController animated:YES]
[activeController presentViewController:loginNavigationController animated:NO completion:nil]

@MatheusAbreu I am using this code to present my navigation controller from NSobject class which is called for logout functionality either from a ViewController or another NSObject class when a session is expired. This code works fine in first run. In second run it give me warning as, "Attempt to present <UINavigationController: 0x15af4110> on <MMDrawerController: 0xe9712d0> whose view is not in the window hierarchy!". I am unable to understand why it's changing the rootviewcontroller the second time.

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 19

You can actually present a modal view Controller from the AppDelegate as long as you detect the current visible viewController and take care of the case where you current controller is a navigationController.

Here is what I do:

UIViewController *activeController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
   activeController = [(UINavigationController*) activeController visibleViewController];
}
[activeController presentModalViewController:loginViewController animated:YES];
[activeController presentModalViewController:loginViewController animated:YES]
[activeController presentViewController:loginNavigationController animated:NO completion:nil]

@MatheusAbreu I am using this code to present my navigation controller from NSobject class which is called for logout functionality either from a ViewController or another NSObject class when a session is expired. This code works fine in first run. In second run it give me warning as, "Attempt to present <UINavigationController: 0x15af4110> on <MMDrawerController: 0xe9712d0> whose view is not in the window hierarchy!". I am unable to understand why it's changing the rootviewcontroller the second time.

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 8

UIViewController *activeController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]])
{
   activeController = [(UINavigationController*) activeController visibleViewController];
}
else if (activeController.modalViewController)
{
    activeController = activeController.modalViewController;
}
[activeController presentModalViewController:vc animated:YES];

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 8

UIViewController *activeController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]])
{
   activeController = [(UINavigationController*) activeController visibleViewController];
}
else if (activeController.modalViewController)
{
    activeController = activeController.modalViewController;
}
[activeController presentModalViewController:vc animated:YES];

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 7

I ran into this problem on iOS 7 - the key to making any of the proposed solutions work was to call

[self.window makeKeyAndVisible];

in your AppDelegate. After that call, presenting a modal view from the window's rootViewController worked.

i'm not loading the storyboard manually so this was it. thanks a million.

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 7

I ran into this problem on iOS 7 - the key to making any of the proposed solutions work was to call

[self.window makeKeyAndVisible];

in your AppDelegate. After that call, presenting a modal view from the window's rootViewController worked.

i'm not loading the storyboard manually so this was it. thanks a million.

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 4

Another reason for that warning can be that you want to present a view controller from an instance which is not the top most view controller.

So first you have to get the topmost UIViewController and using this instance to call presentViewController:

UIViewController *root = [UIApplication sharedApplication].keyWindow.rootViewController;
while (root.presentedViewController) {
    root = root.presentedViewController;
}

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 4

Another reason for that warning can be that you want to present a view controller from an instance which is not the top most view controller.

So first you have to get the topmost UIViewController and using this instance to call presentViewController:

UIViewController *root = [UIApplication sharedApplication].keyWindow.rootViewController;
while (root.presentedViewController) {
    root = root.presentedViewController;
}

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 3

You can NSLog(@"%@", self.window.rootViewController), and see what the rootViewController really is.

I came into this problem, when the rootViewController is a normal UIViewController. Replace it with a UINavigationController, wish it will help.

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 3

You can NSLog(@"%@", self.window.rootViewController), and see what the rootViewController really is.

I came into this problem, when the rootViewController is a normal UIViewController. Replace it with a UINavigationController, wish it will help.

objective c - Attempt to present * on * whose view is not in the windo...

objective-c ios cocoa-touch ios6
Rectangle 27 6

Analysis Because the present modal view ViewController class has not been loaded into the window. This is equivalent to the building, second floor haven't built, directly go to cover 3 floor, this is definitely not. Only after load ViewController's view ;

- (void)viewDidAppear:(BOOL)animated {

 [super viewDidAppear:animated];

    [self showAlertViewController];

}

- (void)showAlertViewController {

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Hello world" message:@"(* 3)( *)d" preferredStyle:UIAlertControllerStyleAlert];

    // Create the actions.

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"hello" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        NSLog(@"The \"Okay/Cancel\" alert's cancel action occured.");
    }];

    UIAlertAction *otherAction = [UIAlertAction actionWithTitle:@"world" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        NSLog(@"The \"Okay/Cancel\" alert's other action occured.");
    }];

    // Add the actions.
    [alertController addAction:cancelAction];
    [alertController addAction:otherAction];

    UIWindow *windows = [[UIApplication sharedApplication].delegate window];
    UIViewController *vc = windows.rootViewController;
    [vc presentViewController:alertController animated: YES completion:nil];
}

Depending on the moment in the "presenting" view controller life, you are trying to present the alertController while the view of the "presenting VC" is not yet "attached" to the window. Basically, trying to present another view controller in the ViewDidLoad won't work, while it will work perfectly in the ViewDidAppear method.

objective c - iOS: Warning "attempt to present ViewController whose vi...

ios objective-c uiactivityviewcontroller presentviewcontroller uiview-hierarchy
Rectangle 27 6

Analysis Because the present modal view ViewController class has not been loaded into the window. This is equivalent to the building, second floor haven't built, directly go to cover 3 floor, this is definitely not. Only after load ViewController's view ;

- (void)viewDidAppear:(BOOL)animated {

 [super viewDidAppear:animated];

    [self showAlertViewController];

}

- (void)showAlertViewController {

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Hello world" message:@"(* 3)( *)d" preferredStyle:UIAlertControllerStyleAlert];

    // Create the actions.

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"hello" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        NSLog(@"The \"Okay/Cancel\" alert's cancel action occured.");
    }];

    UIAlertAction *otherAction = [UIAlertAction actionWithTitle:@"world" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        NSLog(@"The \"Okay/Cancel\" alert's other action occured.");
    }];

    // Add the actions.
    [alertController addAction:cancelAction];
    [alertController addAction:otherAction];

    UIWindow *windows = [[UIApplication sharedApplication].delegate window];
    UIViewController *vc = windows.rootViewController;
    [vc presentViewController:alertController animated: YES completion:nil];
}

Depending on the moment in the "presenting" view controller life, you are trying to present the alertController while the view of the "presenting VC" is not yet "attached" to the window. Basically, trying to present another view controller in the ViewDidLoad won't work, while it will work perfectly in the ViewDidAppear method.

objective c - iOS: Warning "attempt to present ViewController whose vi...

ios objective-c uiactivityviewcontroller presentviewcontroller uiview-hierarchy
Rectangle 27 10

I guess , you are trying to present the alert on view did load. You get the error:

Warning: Attempt to present < UIAlertController: 0x7fb1bb5be040 > on < ViewController: 0x7fb1bb5aef30 > whose view is not in the window hierarchy!

because, in view did load the views are not yet available to display to the user. Hence you cant present the alert. Move the code into viewDidAppear

dispatch_async(dispatch_get_main_queue(), ^ {...});

objective c - Attempt to present UIAlertController on UIViewController...

objective-c uiviewcontroller ios9 hierarchy
Rectangle 27 33

You are trying to present a view controller from the rootViewController. In your case I think the rootViewController is not the current ViewController. Either you presented or pushed a new UIViewController on top of it. You should present a view controller from the top most view controller itself.

UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: activityController animated: YES completion:nil];
[self presentViewController: activityController animated: YES completion:nil];

You can move the method to call another view controller to viewDidAppear:

@TiagoAmaral: The OP's question is different, your comment is not valid in this current context. Also if you are putting that code in viewDidAppear, you need to handle several cases. viewWill/DidAppear methods will be invoked several time (like after a presentedViewController dismisses, after an alert dismisses etc). So you need to handle these cases, if you put that code in viewDidAppear.

what can we do when handling openUrl method?

objective c - iOS: Warning "attempt to present ViewController whose vi...

ios objective-c uiactivityviewcontroller presentviewcontroller uiview-hierarchy
Rectangle 27 32

You are trying to present a view controller from the rootViewController. In your case I think the rootViewController is not the current ViewController. Either you presented or pushed a new UIViewController on top of it. You should present a view controller from the top most view controller itself.

UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: activityController animated: YES completion:nil];
[self presentViewController: activityController animated: YES completion:nil];

You can move the method to call another view controller to viewDidAppear:

@TiagoAmaral: The OP's question is different, your comment is not valid in this current context. Also if you are putting that code in viewDidAppear, you need to handle several cases. viewWill/DidAppear methods will be invoked several time (like after a presentedViewController dismisses, after an alert dismisses etc). So you need to handle these cases, if you put that code in viewDidAppear.

what can we do when handling openUrl method?

objective c - iOS: Warning "attempt to present ViewController whose vi...

ios objective-c uiactivityviewcontroller presentviewcontroller uiview-hierarchy
Rectangle 27 3

UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: activityController animated: YES completion:nil];
//to
[self presentViewController:activityController animated: YES completion:nil];
[self.navigationController pushViewController:activityController animated:YES];

Thanks a lot buddy... i had seen this answer all along...but make sure when you use these code in your bigger use it from main queue not from any child queue otherwise crashses may happen

objective c - iOS: Warning "attempt to present ViewController whose vi...

ios objective-c uiactivityviewcontroller presentviewcontroller uiview-hierarchy
Rectangle 27 3

UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: activityController animated: YES completion:nil];
//to
[self presentViewController:activityController animated: YES completion:nil];
[self.navigationController pushViewController:activityController animated:YES];

Thanks a lot buddy... i had seen this answer all along...but make sure when you use these code in your bigger use it from main queue not from any child queue otherwise crashses may happen

objective c - iOS: Warning "attempt to present ViewController whose vi...

ios objective-c uiactivityviewcontroller presentviewcontroller uiview-hierarchy
Rectangle 27 2

That happen because of two viewcontroller present and dismiss at a same time or you are trying to present ViewController immediately at the viewcontroller open ViewDidload method so

  • Present ViewController from viewDidAppear Method or instead of ViewDidload.

I suggest to make use of completion method for present and dismiss viewcontrolelr like following example:

[self presentViewController:lOTPViewController animated:YES
                             completion:^{

        }];

Create a separate method of presenting a OTPViewController like following:

-(void)PresentOTPViewController
{

    UIStoryboard  *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    OTPViewController *lOTPViewController = [storyboard instantiateViewControllerWithIdentifier:@"OTPViewController"];
    lOTPViewController.comingFromReg = true;

    [self presentViewController:lOTPViewController animated:YES
                     completion:^{}];

}
performSelector
[self performSelector:@selector(PresentOTPViewController) withObject:self afterDelay:1.0 ];

You need to put above performselect code in

[self dismissViewControllerAnimated:YES completion:^{
 [self performSelector:@selector(PresentOTPViewController) withObject:self afterDelay:1.0 ];
}]; // this is the dismiss method of PassCodeViewController

Yah thats the issue is otp vc is dismissed and you immediately present new vc so add 1-2 second delay in between dismiss and new vc present

objective c - iOS whose view is not in the window hierarchy - Stack Ov...

ios objective-c uiview uinavigationcontroller presentviewcontroller