如何同时使用containerView和它的containerView实例化viewController?

时间:2018-02-28 18:57:43

标签: ios swift xcode instantiation childviewcontroller

我想实例化一个带有以下容器的viewController:

let vc = self.storyboard?.instantiateViewController(withIdentifier: ContainerViewController") as? ContainerViewController

我还需要对containerView的引用,所以我尝试以下方法:

let vc2 = vc.childViewControllers[0] as! ChildViewController

应用程序崩溃时,'索引0超出空NSArray的界限'

如何在加载containerViewController之前同时实例化containerViewController和它的childViewController?

修改

用例未经过身份验证后,AWS Cognito将转到signInViewController。此代码位于appDelegate:

func startPasswordAuthentication() -> AWSCognitoIdentityPasswordAuthentication {
    if self.containerViewController == nil {
        self.containerViewController = self.storyboard?.instantiateViewController(withIdentifier: "ContainerViewController") as? ContainerViewController
    }
    if self.childViewController == nil {
        self.childViewController = self.containerViewController!.childViewControllers[0] as! ChildViewController
    }

    DispatchQueue.main.async {
        self.window?.rootViewController?.present(self.containerViewController!, animated: true, completion: nil)
    }
    return self.childViewController!
}

我实例化容器并返回子进程的原因是返回需要符合只有子进程的协议。我想我可以删除容器,但它具有我想要的功能。

1 个答案:

答案 0 :(得分:0)

简短回答:你不能。在您致电instantiateViewController()时,尚未加载视图控制器的视图。您需要以某种方式将其呈现在屏幕上,然后在显示完成后查找它的子视图。

我们需要有关您的用例的更多信息,以便为您提供帮助。

编辑:

好的,有几件事:

如果您在主要主题上调用了startPasswordAuthentication()函数,则无法使用DispatchQueue.main.async进行present()调用。

另一方面,如果在后台线程上调用了您的startPasswordAuthentication()函数,则对instantiateViewController()的调用也属于DispatchQueue.main.async块内,因此它会在主线程。实际上,您可能只想将startPasswordAuthentication()函数的整个主体放在DispatchQueue.main.async块中。

接下来,在调用containerViewController's后,无法加载instantiateViewController(withIdentifier:)子视图控制器。这不是它的工作原理。您应该在当前通话的完成块中查找子视图。

接下来,您不应该进入containerViewController's视图层次结构。您应该向该类添加方法,让您询问您要查找的视图,并使用它们。

如果您尝试编写函数以同步返回子视图控制器,则也无法执行此操作。您需要重写startPasswordAuthentication()函数以获取完成处理程序,并将子视图控制器传递给完成处理程序

所以代码可能会像这样重写:

func startPasswordAuthentication(completion: @escaping (AWSCognitoIdentityPasswordAuthentication?)->void ) {
    DispatchQueue.main.async { [weak self] in
      guard strongSelf = self else {
        completion(nil)
        return
      }
      if self.containerViewController == nil {
        self.containerViewController = self.storyboard?.instantiateViewController(withIdentifier: "ContainerViewController") as? ContainerViewController
      }

      self.window?.rootViewController?.present(self.containerViewController!, animated: true, completion: {
        if strongSelf == nil {
          strongSelf.childViewController = self.containerViewController.getChildViewController()
        }
        completion(strongSelf.childViewController)
      }
    })
}

(该代码被输入到可怕的SO编辑器中,完全没有经过测试,并不是要复制/粘贴。它可能包含需要修复的错误。它只是一个粗略的指导。 )