使用 instantiateViewControllerWithIdentifier 访问相同的视图控制器

Access the identical view controller using instantiateViewControllerWithIdentifier

我在故事板中有一个 UIViewController,故事板 ID 称为 "MyViewController"(嵌入 UINavigationController 作为入口点), 我正在尝试使用 instantiateViewControllerWithIdentifier 从另一个 class 访问它,例如:

MyAccessor.swift

func accessMyViewController(){
  let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
  let vc = storyboard.instantiateViewControllerWithIdentifier("MyViewController")
  print(vc.description)
}

MyViewController.swift

override func viewDidLoad() {
  print(self.description)
}

控制台

<MyViewController: 0x7ff6ab76f9c0>
<MyViewController: 0x7ff6ab557410>

我打印出不同的内存地址,

他们不应该是同一个人吗?

如该方法的 documentation 中所述,它将始终创建一个新实例:

This method creates a new instance of the specified view controller each time you call it.

如果您需要相同的视图控制器实例,则需要将引用存储在其他地方(例如创建第一个实例的视图控制器)。

第一个实例 MyViewController 可能是由故事板本身创建的,因为它是初始视图控制器。

更新:

看了代码再问,终于知道是怎么回事了。 如前所述,导航控制器是故事板的入口点。这意味着 MyViewController 的第一个实例是由故事板创建的,它导致 viewDidLoad 方法中的第一个打印。 第二个实例由 MyAccessor.swift 中的代码创建。同一文件内的打印导致第二个输出行。但是,永远不会加载第二个实例的视图,这会导致永远不会调用 viewDidLoad。如果你在 vc 上调用 loadViewIfNeeded 它将导致第三行输出,它将打印与 MyAccessor.swift 中的 print 相同的内存地址.

可能您的导航控制器是故事板入口点

所以,如果这是真的,那么有两个实例..一个在您的应用程序启动期间创建,另一个从您的代码中以编程方式调用。

P.S.: viewDidLoad不会仅仅通过实例化一个view controller来调用,详见documentation..,否则你已经看到了三个打印..

如果您想立即查看您的情况,请尝试修改您的打印行:

MyAccessor.swift

func accessMyViewController(){
    ...
    print("∙ \(NSStringFromClass(self.dynamicType)) - vc details : \(vc.description) ")
}

MyViewController.swift

override func viewDidLoad() {
    ...
    print("∙ \(NSStringFromClass(self.dynamicType)) - self details : \(self.description) ")
}