【问题标题】:iOS Objective-C: How to identify the view controller is presenting thru UINavigationController?iOS Objective-C:如何识别通过 UINavigationController 呈现的视图控制器?
【发布时间】:2019-10-04 00:00:18
【问题描述】:

例如,我的实现中有多个 viewController:

ViewControllerA
ViewControllerB
ViewControllerC
ViewControllerD

但我需要在 ViewControllerC 中加载深层链接,但我不知道该视图控制器是否已加载(初始化)或是否存在。

我已经从 appDeelegate 尝试过:

ViewControllerC *rootViewController = [[ViewControllerC alloc] init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];

但似乎正在创建 viewController 的新实例。

我的问题是,如何获取实例 ViewControllerC 将其加载到应用程序中,或者如何检测 ViewControllerC 是否尚未加载?

非常感谢您的帮助或解决方法。

【问题讨论】:

  • 显示你的故事板截图
  • @RajeshKumarR,故事板无关。问题是如何获取 ViewControllerC 的相同实例(如果存在)
  • app的rootView控制器是哪个,ViewControllerC和rootviewcontroller有什么关系?

标签: ios objective-c uiviewcontroller uinavigationcontroller appdelegate


【解决方案1】:

正如您所指出的,分配视图控制器以确定它是否呈现是没有意义的。您的应用程序的根目录是否总是有一个导航控制器?如果是这样,你可以这样得到它......

// in the app delegate
AppDelegate *appDelegate = self;

// or, if not in the app delegate
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

// either way
UINavigationController *navController = (UINavigationController *)[[appDelegate window] rootViewController];

注意根 vc 的潜在鲁莽转换为 UINavigationController。仅当某些其他类型的 VC 有时可以作为根源时,这才是鲁莽的。如果您的应用中出现这种情况,那么您需要测试...

UIViewController *vc = [[appDelegate window] rootViewController];
if ([vc isKindOfClass:[UINavigationController self]]) {
    UINavigationController *navController = (UINavigationController *)vc;
    // carry on from here
} else {
    // decide what your "deep link" function does when the wrong root vc is present.  maybe start over?
}

最后,我认为您遇到的问题是,我们如何确定 ViewControllerC 是否存在,如果不存在,我们如何呈现它?第一部分很简单,因为导航控制器有一个viewControllers 属性。这是一个表示“堆栈”的数组,其中第一项是根,最后一项在顶部。所以……

NSInteger index = NSNotFound;
for (UIViewController *vc in navController.viewControllers) {
    if ([vc isKindOfClass:[UIViewController self]]) {
        index = [navController.viewControllers indexOfObject:vc];
    }
}
if (index != NSNotFound) {
    // it's on the stack
}

这是询问它是否在堆栈顶部的方法......

[navController.viewControllers.lastObject isKindOfClass:[ViewControllerC self]]

如果它不在堆栈上怎么办由您决定。一个想法是只推一个。以您已经在应用程序中执行的方式执行此操作。如果它在堆栈上,但不在顶部怎么办?如果你想让动画到达那里,你会弹出它(动画最后一个弹出)。由于这是一个深层链接,您可能不关心动画。只需截断导航控制器视图控制器列表...

if (index != NSNotFound) {
    // it's on the stack
    navController.viewControllers = [navController.viewControllers subarrayWithRange:NSMakeRange(0, index+1)];
}

【讨论】:

    【解决方案2】:

    用于检查根视图控制器是否为 ViewControllerC

    斯威夫特:

    if type(of: UIApplication.shared.keyWindow?.rootViewController) == ViewControllerC.self{
        debugPrint("RootViewController is a ViewControllerC")
    }
    

    目标-C:

    if ([[[[UIApplication sharedApplication] keyWindow] rootViewController] class] == [ViewControllerC class]){
            NSLog(@"RootViewController is a ViewControllerC");
        }
    

    用于检查 ViewControllerC 是否显示在根视图控制器上

    斯威夫特:

    if let rootViewController = UIApplication.shared.keyWindow?.rootViewController{
        if type(of: rootViewController.presentedViewController) == ViewControllerC.self{
            debugPrint("ViewControllerC is presented on rootViewController")
        }
    }
    

    目标-C:

    UIViewController *viewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
        if (viewController != nil){
            if ([viewController.presentedViewController class] == [ViewControllerC class]){
                NSLog(@"ViewControllerC is presented on rootViewController");
            }
        }
    

    将根视图控制器设置为 ViewControllerC

    斯威夫特:

    if UIApplication.shared.keyWindow != nil{
        let viewController:ViewControllerC = ViewControllerC()
        //You can get above instance from Storyboard if you wanna
        UIApplication.shared.keyWindow!.rootViewController = viewController
    }
    

    目标-C:

    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    if (window != nil){
        ViewControllerC *viewController = [[ViewControllerC alloc] init];
        //You can get above instance from Storyboard if you wanna
        window.rootViewController = viewController;
    }
    

    如果存在,则用于从根目录推送导航控制器上的视图控制器

    斯威夫特:

        if UIApplication.shared.keyWindow != nil{
            if let navigationController = UIApplication.shared.keyWindow!.rootViewController as? UINavigationController{
            let viewController:ViewControllerC = ViewControllerC()
            //You can get above instance from Storyboard if you wanna
            navigationController.pushViewController(viewController, animated: true)
            }
        }
    

    目标-C:

    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
        if (window != nil){
            UINavigationController *navigationController = (UINavigationController*)window.rootViewController;
            if (navigationController != nil){
                ViewControllerC *viewController = [[ViewControllerC alloc] init];
                [navigationController pushViewController:viewController animated:true];
            }
        }
    

    现在你可以做很多事情,例如从导航控制器获取 ViewControllerC 的实例(如果存在)

    目标-C:

    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
        if (window != nil){
            UINavigationController *navigationController = (UINavigationController*)window.rootViewController;
            if (navigationController != nil){
                UIViewController *viewController = [navigationController topViewController];
                if ([viewController class] == [ViewControllerC class]){
                    NSLog(@"Do what you want with viewControllerC instance");
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2014-06-30
      • 1970-01-01
      • 2013-09-19
      • 2016-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2012-07-24
      相关资源
      最近更新 更多