模态视图控制器不在窗口层次结构中

3

我正在开发的应用程序有一个选项卡控制器。

当应用程序启动时,我在AppDelegate中获取用户位置,当我获得所需的准确度时,AppDelegate会向我的应用程序起始页面(选项卡控制器的索引0)发送一个NSNotification。

在接收到通知后,此视图尝试使用用户坐标和其他数据发送电子邮件,但是一旦呈现MFMailComposeViewController,我就会收到以下错误:

Warning: Attempt to present <MFMailComposeViewController: 0x98a0270> on <UITabBarController: 0x988c630> whose view is not in the window hierarchy!

我漏掉了什么?

谢谢。

编辑:添加一些代码...

这是我在AppDelegate.m中的代码:

- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSUserDefaults *phoneNumbers = [NSUserDefaults standardUserDefaults];
NSDate *eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 10.0) {
    [self locationUpdate:newLocation];
    smsLoc = newLocation;
    if ([[phoneNumbers objectForKey:@"sendSMS"] isEqualToString:@"yes"]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"sendSMS" object:nil];
    } else if ([[phoneNumbers objectForKey:@"sendEmail"] isEqualToString:@"yes"]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"sendEmail" object:nil];
    }

}
}

然后,在我的第一个视图控制器中,我有:

- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sendSMS:) name:@"sendSMS" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sendEmail:) name:@"sendEmail" object:nil];
}

最后,"sendSMS" 的选择器(另一个也非常相似):

- (void)sendSMS: (NSNotification *)notification {
NSUserDefaults *phoneNumbers = [NSUserDefaults standardUserDefaults];
if ([phoneNumbers objectForKey:@"first"] || [phoneNumbers objectForKey:@"second"]) {
        MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
        if ([MFMessageComposeViewController canSendText]) {
            AppDelegate *deleg = (AppDelegate *)[[UIApplication sharedApplication] delegate];
            controller.body = [NSString stringWithFormat:@"some message with coordinates %.4f - %.4f", [deleg currentLocation].coordinate.latitude, [deleg currentLocation].coordinate.longitude];
            controller.recipients = [NSArray arrayWithObjects:[phoneNumbers objectForKey:@"first"], [phoneNumbers objectForKey:@"second"], nil];
            controller.messageComposeDelegate = self;
            [self presentModalViewController:controller animated:YES];
        }
    }
}
}

第二次编辑:添加更多代码。
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.delegate = self;
tabBarController.selectedIndex = 0;
[[tabBarController.tabBar.items objectAtIndex:0] setTitle:NSLocalizedString(@"Home", nil)];
[[tabBarController.tabBar.items objectAtIndex:1] setTitle:NSLocalizedString(@"Requests", nil)];
[[tabBarController.tabBar.items objectAtIndex:2] setTitle:NSLocalizedString(@"Account", nil)];
[[tabBarController.tabBar.items objectAtIndex:3] setTitle:NSLocalizedString(@"Settings", nil)];
//some other controls from DB
[[tabBarController.tabBar.items objectAtIndex:1] setBadgeValue:[NSString stringWithFormat:@"%d",number]];

tabbarController已通过IB创建,但我在AppDelegate中添加了上面的代码,因为我需要本地化选项卡栏项目并向其中一个添加标记。

我在这里做错了什么吗?


你能否发布一些代码,展示你如何处理通知? - jere
错误出现在其他地方,可能是在applicationDidFinishLaunching中设置UIWindow和UITabbarController时。 - Felix
编辑问题,以包括 applicationDidFinishLaunching。 - Aleph72
4个回答

10

我不确定您是否解决了这个问题。错误信息意味着您用于呈现另一个模态视图控制器的视图控制器在窗口上不可见。这可能是由于以下原因引起的:

[VC1 presentModalViewController:VC2];

// Error here, since VC1 is no longer visible on the window
[VC1 presentModalViewController:VC3]; 

如果您的问题像上面那样,您可以这样解决:

if (self.modalViewController != nil) {
    [self.modalViewController presentModalViewController:VC3 animated:YES];
} else {
    [self.tabBarController presentModalViewController:VC3 animated:YES];
}

如果那个方法没有解决你的问题,也许你可以尝试使用self.tabBarController代替self进行演示。这仅仅是一个建议,我不确定它是否有效。


谢谢你的回答。最后我改了很多东西,不确定为什么错误就消失了。无论如何,你的答案对我来说是正确的,所以我会将其标记为正确答案。 - Aleph72
你所需要做的一件事情就是把一些代码移到 self.window makeKeyAndVisible 之后。因为如果你在此之前编写代码,那么视图还没有被创建出来。 - Srikanth

2

以下翻译可能有助于您理解: [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:picker animated:NO completion:nil];


这很有帮助!!! - tsukimi

1

由于 modalViewController 和 presentModalViewController 已被弃用,以下是适合我的解决方法:

presentingVC = [[UIApplication sharedApplication] keyWindow].rootViewController;
if (presentingVC.presentedViewController) {
    [presentingVC.presentedViewController presentViewController:VC3 animated:YES completion:nil];
} else {
    [presentingVC presentViewController:VC3 animated:YES completion:nil];
}

0

你可以按照这个模式进行操作

[VC1 presentModalViewController:VC2];

//
[**VC2** presentModalViewController:VC3]; 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接