从应用程序委托获取当前的视图控制器(模态是可能的)
我知道,从应用程序委托获取当前的视图控制器,我可以使用我为我的应用程序设置的navigationController
属性。 但是,在我的应用程序的许多地方都可能会出现模态导航控制器。 有没有什么办法来检测这个从应用程序委托,因为当前的导航控制器将不同于应用程序委托持有一个参考?
我build议你使用NSNofiticationCenter。
//in AppDelegate: @interface AppDelegate() { ... id lastViewController; ... } @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleCurrentViewController) name:@"CurrentViewController" object:nil]; ... } - (void)handleCurrentViewController:(NSNotification *)notification { if([[notification userInfo] objectForKey:@"lastViewController"]) { lastViewController = [[notification userInfo] objectForKey:@"lastViewController"]; } } - (void)applicationDidEnterBackground:(UIApplication *)application { NSLog(@"last view controller is %@", [(UIViewController *)lastViewController class]); } @end //in every ViewController you want to detect @implementation SomeViewController ... - (void) viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] postNotificationName:@"CurrentViewController" object:nil userInfo:[NSDictionary dictionaryWithObjectsAndKeys:self, @"lastViewController", nil]]; } ... @end
基于这里的要点 ,我做了一个类来获得最顶级的视图控制器,这样调用[[UIApplication sharedApplication] topMostViewController]
会给你在你的应用程序中最顶级的视图控制器。
这在iOS 8中特别有用,其中UIAlertView
和UIActionSheet
已被弃用,而UIAlertController
需要在最顶层的视图控制器上显示。
的UIViewController + TopMostViewController.h
#import <UIKit/UIKit.h> @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 #pragma mark - @implementation UIApplication (TopMostViewController) - (UIViewController *)topMostViewController { return [self.keyWindow.rootViewController topMostViewController]; } @end
这对我有效。 我有很多目标有不同的控制器,所以以前的答案似乎没有工作。
首先你需要在你的AppDelegate类中:
var window: UIWindow?
然后,在你的function
let navigationController = window?.rootViewController as? UINavigationController if let activeController = navigationController!.visibleViewController { if activeController.isKindOfClass( MyViewController ) { println("I have found my controller!") } }
你可以尝试通过做最顶级的观点 :
[[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];
尽pipe这种观点可能是隐形的,甚至可以被某些子视图所覆盖。
这取决于你的用户界面,但它可能有帮助。
Swift中的很好的解决scheme,在AppDelegate中实现
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 }
目标 – 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; } }
如果在App Delegate中有导航控制器,只需使用visibleViewController属性即可。 它会给你可见的控制器,即使它是一个模式。
在swift中,你可以像这样获得活动的ViewController:
let navigationController = application.windows[0].rootViewController as UINavigationController let activeViewCont = navigationController.visibleViewController
最好的解决scheme,也moreNavigationController
于UITabBarController
moreNavigationController
:
extension UIApplication { class func topViewController(base: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? { if let nav = base as? UINavigationController { return topViewController(nav.visibleViewController) } if let tab = base as? UITabBarController { let moreNavigationController = tab.moreNavigationController if let top = moreNavigationController.topViewController where top.view.window != nil { return topViewController(top) } else if let selected = tab.selectedViewController { return topViewController(selected) } } if let presented = base?.presentedViewController { return topViewController(presented) } return base } }
下面的代码工作得很好。
+(UIViewController *)findBestViewController:(UIViewController *)vc {
if (vc.presentedViewController) { // Return presented view controller return [AppDelegate findBestViewController:vc.presentedViewController]; } else if ([vc isKindOfClass:[UISplitViewController class]]) { // Return right hand side UISplitViewController* svc = (UISplitViewController*) vc; if (svc.viewControllers.count > 0) return [AppDelegate findBestViewController:svc.viewControllers.lastObject]; else return vc; } else if ([vc isKindOfClass:[UINavigationController class]]) { // Return top view UINavigationController* svc = (UINavigationController*) vc; if (svc.viewControllers.count > 0) return [AppDelegate findBestViewController:svc.topViewController]; else return vc; } else if ([vc isKindOfClass:[UITabBarController class]]) { // Return visible view UITabBarController* svc = (UITabBarController*) vc; if (svc.viewControllers.count > 0) return [AppDelegate findBestViewController:svc.selectedViewController]; else return vc; } else { // Unknown view controller type, return last child view controller return vc; }
}
+(UIViewController *)currentViewController {
// Find best view controller UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController; return [AppDelegate findBestViewController:viewController];
}
上面的其他解决scheme的工作只是部分复杂的视图层次不处理(导航控制器集成在标签栏控制器,分割视图控制器,视图容器和警报控制器可能会搞砸)。
我通过在AppDelegate中保留当前视图控制器的引用来解决这个问题。 每次出现视图时,我都会利用
viewDidAppear(animated:)
并在应用程序委托中设置引用。
我知道这个问题是关于Objective-C的,但是我只能提供Swift代码,我相信这对两种types的用户都是有用的。
首先:我已经实现了一个协议来保持事物的清洁和可重用:
protocol UpdatableViewController { func updateUI() }
第二:我已经添加了对AppDelegate的引用:
var currentViewController: UpdatableViewController?
第三:我在viewDidAppear()中设置当前视图控制器:
override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate appDelegate?.currentViewController = self }
第四:
extension ViewController1: UpdatableViewController { func updateUI() { print("Implement updating here") } }
- 我怎样才能得到UITextFieldDelegate.shouldChangeCharactersInRange与自定义inputView触发?
- Apple Push – didReceiveIncomingPushWithPayload未被调用 – 而是错误:发送消息失败到客户端
- 从应用程序委托获取当前的视图控制器
- NSURLConnection不会跨多个视图调用完成
- 如何使用应用程序委托中的视图控制器的function?
- 把委托方法放到一个类别中
- Dropbox的SDK – linkFromController:委托或callback?
- 代表里面的Obj-C代表
- 我的自定义viewcontroller委托不工作