Deinit没有调用UIViewController,但是Dealloc是
看起来像dealloc
的Swift相当于deinit
。 但是,当您尝试在UIViewController上定义方法时,它不会像您所期望的那样运行…
build立
- 使用Xcode 7.0在Swift或Objective-C中创build一个新的Single View项目。
- 在用故事板创build的视图控制器上添加一个“解除”button(我将这个视图控制器称为VC2;它的类是ViewController)。
- 添加一个新的视图控制器,并将其设置为初始视图控制器(VC1,类为零)。
- 向VC1添加“呈现”button,将“呈现模式”延续到VC2。
- 在VC2的代码中,在
deinit
(Swift)或dealloc
(Objective-C)中放置一个断点。 -
在VC2中,使“解除”button的操作执行以下操作:
// Swift: presentingViewController?.dismissViewControllerAnimated(true, completion: nil) // Objective-C: [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
- 运行该应用程序,并点击两个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,但是看起来断点在deinit
performance看起来不像你的代码中的其他任何地方。
我会告诉你几个例子,我在每行号上添加一个断点。 那些将工作(例如暂停执行或执行诸如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中放置一个打印语句,并报告您的发现