Question

I'm calling a method from viewcontroller in an appdelegate. When I was testing functionality I just used NSLog message which works fine (so the connection between viewcontroller and appdelegate is OK). The problem appears once I add a email form into this method. The message I receive is:

Warning: Attempt to present <MFMailComposeViewController: 0x1fdc3990> on <ViewController: 0x1fd9e3b0> whose view is not in the window hierarchy!

Anyone who know what to do? I know there are lot of topics with 'whose view is not in the window hierarchy' issue but none of them helped me.

ViewController.m

...
-(void)mail{
    NSLog(@"blablabla");
    if ([MFMailComposeViewController canSendMail]) {

        MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
        mail.mailComposeDelegate = self;

        [mail setSubject:@"Hello and welcome!"];

        NSArray *toRecipients = [NSArray arrayWithObject:@"tomas.javnicky@gmail.com"];
        [mail setToRecipients:toRecipients];
        [mail setCcRecipients:toRecipients];

        NSString *emailBody = @"Hey all!";
        [mail setMessageBody:emailBody isHTML:NO];

        mail.modalPresentationStyle = UIModalPresentationPageSheet;
        [self presentViewController:mail animated:YES completion:nil];


    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error!"
                                                        message:@"E-mail is not supported on your device"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    }
}

-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{

    switch (result) {
        case MFMailComposeResultCancelled:
            break;
        case MFMailComposeResultSaved:
            NSLog(@"mail saved");
            break;
        case MFMailComposeResultSent:
            NSLog(@"mail sent");
            break;
        case MFMailComposeResultFailed:
            NSLog(@"mail failed");
            break;
    }
    [self dismissViewControllerAnimated:YES
                             completion:nil];
}
...

Appdelegate.m

...
-(void)something {
     ViewController * vc = [[ViewController alloc] init];
     [vc mail];
}
...

This is what solved my problem:

- (void)something {
    ViewController *rootViewController = (ViewController*)self.window.rootViewController;
    [rootViewController mail];
}

Also check the answer by rmaddy for more info.

Was it helpful?

Solution

Now that you've posted code, the problem is obvious. You create a view controller but you never display it (in the something method). Then you call a method on this undisplayed view controller (mail) which attempts to display the mail view controller from the undisplayed view controller. This is what causes the error.

You need to display the mail controller from a view controller that is already being displayed (such as the rootViewController maybe).

What is the point of your ViewController class?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top