所有视图控制器转换完成后,应用委托检查

时间:2014-07-11 07:13:35

标签: ios objective-c push-notification protocols appdelegate

我希望我的应用能够响应远程推送到我的设备。我想要做的是将视图控制器作为对推送通知的响应。

当应用程序运行时,这样做没有问题。从应用程序委托开始,我首先获取根视图控制器并一直向上,以便找到可见的视图控制器并在其上显示一个新的控制器。像魅力一样工作。

当应用程序启动时,我首先显示根视图控制器,然后检查是否有任何缓存的数据存储在设备上,如果是,它会加载一个新的视图控制器来呈现它。有时它需要2s,有时需要让7s说。当应用程序全部完成呈现新的视图控制器时,无法确定操作将花费多长时间。因此,如果我想在发布后立即呈现视图控制器,情况会变得棘手。

目前我使用的hacky版本依赖于dispatch_after代码段,该代码段会在应用启动后的5s左右触发演示文稿。它在95%的情况下有效,但我不喜欢这个解决方案。

所以我的问题是:当所有模态转换完成且我的应用程序处于"稳定的最终版本时,如何在appDelegate中收到通知? (这样我可以得到最顶层的视图控制器,并且没有任何伤害地呈现在它上面)状态?

我可以粘贴一些我已经使用的代码,如果这样做会有所帮助。

修改
我被要求粘贴一些代码,以便我如何从app delegate呈现视图控制器。调用application:didFinishLaunchingWithOptions:并且UIApplicationLaunchOptionsRemoteNotificationKey词典中有launchOptions条目时,会调用下面的代码段。

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    UIViewController *controller = [self topViewControllerFromController:self.window.rootViewController];
    NSInteger messageID = [userInfo[@"m_id"] integerValue];

    MessageViewController *mvc = [[MessageViewController alloc] initWithMessageID:messageID];
    mvc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;

    [controller presentViewController:mvc animated:YES completion:nil];
});

topViewController非常简单:

- (UIViewController *)topViewControllerFromController:(UIViewController *)controller
{
    if (controller.presentedViewController)
    {
        UIViewController *presentedViewController = controller.presentedViewController;
        return [self topViewControllerFromController:presentedViewController];
    }
    else if ([controller isKindOfClass:[UINavigationController class]])
    {
        UINavigationController *navigationController = (UINavigationController *)controller;
        return [self topViewControllerFromController:navigationController.visibleViewController];
    }
    else if ([controller isKindOfClass:[UITabBarController class]])
    {
        UITabBarController *tabBarController = (UITabBarController *)controller;
        return [self topViewControllerFromController:tabBarController.selectedViewController];
    }
    else
    {
        return controller;
    }
}

现在演示文稿和内容工作正常,并且没有任何问题。我只需要知道所有模态转换何时完成,即。当应用程序很好地呈现另一个。

1 个答案:

答案 0 :(得分:2)

如果您有一个固定的视图层次结构,表示要显示的最终视图,您可以:

A)最简单,发布来自[edit:] viewDidAppear:任何“加载链末端”视图控制器的方法的通知。顺便说一下,你应该在一个块中使用一个弱的自我引用,就像你所显示的那样(见下文,在块中使用selfRef,而不是关键字self)。如果你不这样做,它将产生一个保留周期,你的应用程序将保留在内存中(技术上不是泄漏,但具有类似的效果)。在这种情况下,可能无关紧要,因为你的应用程序不太可能在切换topViewController时,因此在这种情况下它不太可能对内存产生净负面影响,但仍然作为一个风格点很重要。 :

appDelegate中的某个地方(例如在应用程序中:didFinishLaunching:withOptions:method)

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
__weak UIViewController *selfRef = self;

[center addObserverForName:@"AllViewsLoaded" object:nil queue:nil usingBlock:^(NSNotification *note) 
{
    UIViewController *controller = [selfRef topViewControllerFromController: selfRef.window.rootViewController];
    NSInteger messageID = [userInfo[@"m_id"] integerValue];

    MessageViewController *mvc = [[MessageViewController alloc] initWithMessageID:messageID];
    mvc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;

    [controller presentViewController:mvc animated:YES completion:nil];
}];

然后在viewDidAppear:任何“行结束”视图控制器的方法:

[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"AllViewsLoaded" object:nil]];

B)或者,你可以定义一个协议 - 例如在你的最终视图控制器的.h文件中:

@protocol FinalViewLoadedAndDisplayedProtocol
 - (void)viewFinallyLoaded:(UIViewController*)finalViewControllerThatLoaded; 
@end

在你的app appate中定义方法:

- (void)viewFinallyLoaded:(UIViewController*)finalViewControllerThatLoaded {
    UIViewController *controller = [self topViewControllerFromController: self.window.rootViewController];
    NSInteger messageID = [userInfo[@"m_id"] integerValue];

    MessageViewController *mvc = [[MessageViewController alloc] initWithMessageID:messageID];
    mvc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;

    [controller presentViewController:mvc animated:YES completion:nil];
}

将协议支持添加到App delegate .h文件中。然后在最终视图控制器的.m文件中:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    MainClass *appDelegate = (id)[[UIApplication sharedApplication] delegate];

    if ([appDelegate respondsToSelector:@selector(viewFinallyLoaded:)]) {
       [self.viewDidLoadDelegate viewFinallyLoaded:self];
    }
}