从应用程序委托获取当前视图控制器(可能是模态的)

6 浏览
0 Comments

从应用程序委托获取当前视图控制器(可能是模态的)

我知道可以通过使用我为应用程序设置的navigationController属性来获取当前的视图控制器。然而,在我的应用程序中的许多地方可能会呈现模态导航控制器。有没有办法从应用程序委托中检测到这一点,因为当前的导航控制器将与应用程序委托持有引用的导航控制器不同?

0
0 Comments

问题出现的原因是需要获取当前的视图控制器,包括模态视图控制器。解决方法是在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吗?我现在无法测试,但我担心它不起作用。

0
0 Comments

问题的出现原因:

在应用程序进入后台或者锁屏时,viewWillDisappear方法不会被调用,而是直接调用applicationDidEnterBackground方法。

解决方法:

使用NSNotificationCenter来处理当前视图控制器。在AppDelegate中添加一个观察者,监听名为"CurrentViewController"的通知。在每个需要检测的视图控制器中,当视图即将消失时,发送一个名为"CurrentViewController"的通知,并将当前视图控制器作为userInfo中的参数传递。在AppDelegate的handleCurrentViewController方法中,接收到通知后将传递的视图控制器保存在lastViewController变量中。在applicationDidEnterBackground方法中,通过打印lastViewController的类名来获取当前视图控制器。

另外,也可以使用NSUserDefaults来保存最后一个活动的视图控制器名称。在每个视图控制器的viewWillAppear方法中,将当前视图控制器的名称保存在NSUserDefaults字段中。这样就可以在整个应用程序中访问用户最后使用的活动视图。

此外,还可以使用applicationWillResignActive方法,在应用程序进入后台之前进行操作。

最后,在开发者文档中可以找到有关UIApplicationDelegate协议的更多信息。

0
0 Comments

原因:在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`可能不再是一个属性。

0