当所有视图控制器转换完成时,应用程序委托检查

Posted

技术标签:

【中文标题】当所有视图控制器转换完成时,应用程序委托检查【英文标题】:App delegate check when all view controller transitions finished 【发布时间】:2014-07-11 07:13:34 【问题描述】:

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

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

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

目前我正在使用依赖于dispatch_after sn-p 的 hacky 版本,它会在应用启动后 5 秒左右触发演示。它适用于 95% 的情况,但我不喜欢这种解决方案。

所以我的问题是:当所有模态转换都完成并且我的应用程序处于“稳定的最终状态”时,我如何才能在appDelegate 中收到通知(这样我就可以获得最顶层的视图控制器并在没有伤害)状态?

如果有任何帮助,我可以粘贴一些我已经在使用的代码。

编辑 我被要求粘贴一些代码,如何从应用程序委托中呈现视图控制器。当调用application:didFinishLaunchingWithOptions: 并且launchOptions 字典中有UIApplicationLaunchOptionsRemoteNotificationKey 条目时,将调用下面的sn-p。

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;
    

现在演示文稿和内容可以正常工作,并且没有问题。我只需要知道所有模态转换何时完成,即。当应用适合展示另一个应用时。

【问题讨论】:

您必须粘贴一些代码,您是如何从 App 委托中呈现视图控制器的? 你可以在 appDelegate 中设置 status 的值,然后观察它。 @rishi 用一些代码和解释编辑了帖子。技巧 14 然后我必须从应用程序中的每个视图控制器设置该值,以便它在没有控制器动画时反映。我认为这不是一个很好的解决方案。 【参考方案1】:

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

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

在您的 appDelegate 中的某处(例如在 application:didFinishLaunching:withOptions: 方法中)

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

在您的应用委托中定义方法:

- (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 委托 .h 文件添加对协议的支持。然后在最终视图控制器的.m文件中:

- (void)viewDidAppear:(BOOL)animated

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

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

【讨论】:

以上是关于当所有视图控制器转换完成时,应用程序委托检查的主要内容,如果未能解决你的问题,请参考以下文章

按下远程通知时打开视图控制器

animationDidStop:完成:委托方法没有被调用

应用程序首次运行时加载所有标签栏视图

应用程序在模态显示视图控制器时崩溃

如何从视图控制器调用所有方法和函数到应用程序委托?

应用委托访问环境对象