Deinit没有调用UIViewController,但是Dealloc是

看起来像dealloc的Swift相当于deinit 。 但是,当您尝试在UIViewController上定义方法时,它不会像您所期望的那样运行…

build立

  1. 使用Xcode 7.0在Swift或Objective-C中创build一个新的Single View项目。
  2. 在用故事板创build的视图控制器上添加一个“解除”button(我将这个视图控制器称为VC2;它的类是ViewController)。
  3. 添加一个新的视图控制器,并将其设置为初始视图控制器(VC1,类为零)。
  4. 向VC1添加“呈现”button,将“呈现模式”延续到VC2。
  5. 在VC2的代码中,在deinit (Swift)或dealloc (Objective-C)中放置一个断点。
  6. 在VC2中,使“解除”button的操作执行以下操作:

     // Swift: presentingViewController?.dismissViewControllerAnimated(true, completion: nil) // Objective-C: [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 
  7. 运行该应用程序,并点击两个button,首先提出VC2,然后解雇它。

注意在Objective-C中dealloc断点是如何被命中的

另一方面,在Swift中deinit断点永远不会被deinit

为什么deinit从不被调用? 这是一个错误还是devise?

如果这是devise,那么当不再需要视图控制器时,我应该在哪里放置清理代码以释放资源? (它不能在viewDidUnload因为这个方法已经被弃用了,它不能在viewDidDisappear因为别的东西可能持有对它的引用,并且最终会再次显示它。)


注意:如果你试图在Swift中定义一个dealloc方法,你会得到下面的错误:

使用Objective-Cselect器“dealloc”的方法“dealloc()”与具有相同Objective-Cselect器的deinitializer冲突。

如果你有从一个Objective-C控制器inheritance的Swift视图控制器,并且你在Objective-C dealloc方法中放置一个断点,你将得到与上面定义的相同的错误行为: deinit不会被调用,但dealloc将调用。

如果您尝试使用Allocations查看内存中类的实例数,则两个版本都显示相同的内容: # Persistent始终为1,并且每次显示第二个视图控制器时# Transient增加。

鉴于上述设置,应该没有强大的参考周期坚持视图控制器。

TLDR:

如果在它们之前有一个可执行的代码行,断点只能在deinit下工作。

  • 如果你在一行可执行代码中放置一个断点,那么它将起作用。
  • 可执行的代码行必须属于deinit方法。

感谢Adam帮助我指出了正确的方向 。 我没有进行大量的testing,但是看起来断点在deinitperformance看起来不像你的代码中的其他任何地方。

我会告诉你几个例子,我在行号上添加一个断点。 那些将工作(例如暂停执行或执行诸如logging消息的动作)将通过<符号来指示。

通常情况下,即使一个方法什么都不做,断点也会受到打击:

 ➤ 1 ➤ 2 func doNothing() { ➤ 3 ➤ 4 } 5 

然而,在一个空白的deinit方法中, 没有任何断点会被击中:

  1 2 deinit { 3 4 } 5 

通过添加更多的代码行,我们可以看到它取决于断点之后是否有可执行的代码行:

 ➤ 1 ➤ 2 deinit { ➤ 3 // ➤ 4 doNothing() ➤ 5 // ➤ 6 foo = "abc" 7 // 8 } 9 

特别是要注意第7行和第8行,因为这跟doNothing()行为差别很大!

如果你已经习惯了第4行的断点如何在doNothing()工作的doNothing() ,那么你可能会错误地推断出你的代码没有执行,如果你在这个例子中只有第5行(甚至是第4行)有一个断点:

 ➤ 1 ➤ 2 deinit { ➤ 3 number++ 4 // incrementNumber() 5 } 6 

注意:对于在同一行中暂停执行的断点,它们按创build的顺序被命中。 为了testing它们的顺序,我设置了一个断点到日志消息,在评估操作后自动继续

注意:在我的testing中,还有另一个潜在的问题可能会让你:如果你使用print("test") ,它会popupDebug Area来显示你的消息(消息以粗体显示)。 但是,如果您添加一个断点并将其告诉日志消息 ,它将以常规文本logging,而不是popup打开debugging区域。 您必须手动打开debugging区域才能看到输出。

注意:这全部在Xcode 7.1.1中testing过

我还没有尝试过,但我确实为你find了这个 :

看起来这个函数不会被调用,除非有一些代码放在deinit(怪异的)里面,一定是swift优化阶段的一部分。

尝试按照build议在您的deinit中放置一个打印语句,并报告您的发现