我想实例化一个带有以下容器的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!
}
我实例化容器并返回子进程的原因是返回需要符合只有子进程的协议。我想我可以删除容器,但它具有我想要的功能。
简答:你做不到。在您调用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编辑器中,完全没有经过测试,并且不打算复制/粘贴。它可能包含需要修复的错误。这只是一个粗略的指导。)