从应用程序委托获取当前视图控制器(可能是模态的)
问题出现的原因是需要获取当前的视图控制器,包括模态视图控制器。解决方法是在AppDelegate中实现一个方法,使用递归的方式遍历视图控制器层级,找到最顶层的视图控制器。
在Swift中,可以使用以下代码实现:
func getTopViewController()->UIViewController{
return topViewControllerWithRootViewController(UIApplication.sharedApplication().keyWindow!.rootViewController!)
}
func topViewControllerWithRootViewController(rootViewController:UIViewController)->UIViewController{
if rootViewController is UITabBarController{
let tabBarController = rootViewController as! UITabBarController
return topViewControllerWithRootViewController(tabBarController.selectedViewController!)
}
if rootViewController is UINavigationController{
let navBarController = rootViewController as! UINavigationController
return topViewControllerWithRootViewController(navBarController.visibleViewController)
}
if let presentedViewController = rootViewController.presentedViewController {
return topViewControllerWithRootViewController(presentedViewController)
}
return rootViewController
}
在Objective-C中,可以使用以下代码实现:
- (UIViewController*)topViewController { return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController]; } - (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController { if ([rootViewController isKindOfClass:[UITabBarController class]]) { UITabBarController* tabBarController = (UITabBarController*)rootViewController; return [self topViewControllerWithRootViewController:tabBarController.selectedViewController]; } else if ([rootViewController isKindOfClass:[UINavigationController class]]) { UINavigationController* navigationController = (UINavigationController*)rootViewController; return [self topViewControllerWithRootViewController:navigationController.visibleViewController]; } else if (rootViewController.presentedViewController) { UIViewController* presentedViewController = rootViewController.presentedViewController; return [self topViewControllerWithRootViewController:presentedViewController]; } else { return rootViewController; } }
这个方法可以处理UISplitViewController吗?我现在无法测试,但我担心它不起作用。
问题的出现原因:
在应用程序进入后台或者锁屏时,viewWillDisappear方法不会被调用,而是直接调用applicationDidEnterBackground方法。
解决方法:
使用NSNotificationCenter来处理当前视图控制器。在AppDelegate中添加一个观察者,监听名为"CurrentViewController"的通知。在每个需要检测的视图控制器中,当视图即将消失时,发送一个名为"CurrentViewController"的通知,并将当前视图控制器作为userInfo中的参数传递。在AppDelegate的handleCurrentViewController方法中,接收到通知后将传递的视图控制器保存在lastViewController变量中。在applicationDidEnterBackground方法中,通过打印lastViewController的类名来获取当前视图控制器。
另外,也可以使用NSUserDefaults来保存最后一个活动的视图控制器名称。在每个视图控制器的viewWillAppear方法中,将当前视图控制器的名称保存在NSUserDefaults字段中。这样就可以在整个应用程序中访问用户最后使用的活动视图。
此外,还可以使用applicationWillResignActive方法,在应用程序进入后台之前进行操作。
最后,在开发者文档中可以找到有关UIApplicationDelegate协议的更多信息。
原因:在iOS 8中,UIAlertView和UIActionSheet被废弃,推荐使用UIAlertController代替。UIAlertController需要在最顶层的视图控制器上展示,所以需要获取当前的视图控制器。
解决方法:根据给出的gist,创建了一个类别(category)来获取最顶层的视图控制器。通过调用`[[UIApplication sharedApplication] topMostViewController]`可以获取应用程序中最顶层的视图控制器。具体的实现代码如下:
UIViewController+TopMostViewController.h:
#import@interface UIViewController (TopMostViewController) - (UIViewController *)topMostViewController; @end @interface UIApplication (TopMostViewController) - (UIViewController *)topMostViewController; @end
UIViewController+TopMostViewController.m:
#import "UIViewController+TopMostViewController.h" @implementation UIViewController (TopMostViewController) - (UIViewController *)topMostViewController { if (self.presentedViewController == nil) { return self; } else if ([self.presentedViewController isKindOfClass:[UINavigationController class]]) { UINavigationController *navigationController = (UINavigationController *)self.presentedViewController; UIViewController *lastViewController = [[navigationController viewControllers] lastObject]; return [lastViewController topMostViewController]; } UIViewController *presentedViewController = (UIViewController *)self.presentedViewController; return [presentedViewController topMostViewController]; } @end @implementation UIApplication (TopMostViewController) - (UIViewController *)topMostViewController { return [self.keyWindow.rootViewController topMostViewController]; } @end
需要注意的是,可能需要将.h和.m文件中的代码进行调换。
根据回答中的评论,Swift 2的语法可能已经发生了变化,`topMostViewController`可能不再是一个属性。