当所有视图控制器转换完成时,应用程序委托检查
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];
【讨论】:
以上是关于当所有视图控制器转换完成时,应用程序委托检查的主要内容,如果未能解决你的问题,请参考以下文章