它seems like the Swift equivalent of dealloc
is deinit
.但是,当您尝试在 UIViewController 上定义该方法时,它的行为并不像您期望的那样...
设置
- 使用 Xcode 7.0 在 Swift 或 Objective-C 中创建一个新的单 View 项目。
- 在使用 Storyboard创建的 View Controller 上添加一个“关闭”按钮(我将此 View Controller 称为 VC2;它的类是 ViewController)。
- 添加一个新的 View Controller 并将其设置为初始 View Controller (VC1,类为nil)。
- 向 VC1 添加一个“present”按钮,向 VC2 添加一个“Present Modally”segue。
- 在 VC2 的代码中,在
deinit
(Swift) 或dealloc
(Objective-C) 中放置一个断点。 在 VC2 中,使“关闭”按钮的操作执行以下操作:
// Swift: presentingViewController?.dismissViewControllerAnimated(true, completion: nil) // Objective-C: [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
- 运行应用并点按两个按钮以首先显示 VC2,然后关闭它。
注意在 Objective-C 中,dealloc
断点是如何命中的。
另一方面,在 Swift 中,deinit
断点永远不会命中。
为什么从未调用过deinit
?这是错误还是设计使然?
如果这是设计使然,当不再需要 View Controller 时,我应该在哪里放置清理代码以释放资源? (它不能在 viewDidUnload
中,因为该方法已被弃用。它不能在 viewDidDisappear
中,因为其他东西可能持有对它的引用并最终显示它再次。)
注意:如果您尝试在 Swift 中定义 dealloc
方法,您会收到以下错误:
Method 'dealloc()' with Objective-C selector 'dealloc' conflicts with deinitializer with the same Objective-C selector.
如果您让 Swift View Controller 继承自 Objective-C Controller ,并在 Objective-C 的 dealloc 方法中放置一个断点,您将得到与上面定义的相同的错误行为:deinit
不会被调用,但是 dealloc
会被调用。
如果您尝试使用 Allocations 查看内存中类的实例数,两个版本显示相同的内容:#Persistent
始终为 1,而 #Transient
每次显示第二个 View Controller 时都会增加。
鉴于上述设置,应该没有 strong reference cycle坚持 View Controller 。
最佳答案
简单描述:
只有在断点前面有可执行代码行时,断点才会在 deinit
中起作用。
- 如果您在一行可执行代码上放置一个断点,那么它将起作用。
- 可执行的代码行必须属于
deinit
方法。
感谢Adam for pointing me in the right direction .我没有进行广泛的测试,但看起来断点在 deinit
中的行为与代码中其他地方的行为不同。
我将向您展示几个示例,其中我在每个 行号上添加了一个断点。那些将起作用的(例如暂停执行或执行它们的操作,例如记录消息)将通过 ➤ 符号指示。
通常情况下,断点会被随意命中,即使方法什么都不做也是如此:
➤ 1
➤ 2 func doNothing() {
➤ 3
➤ 4 }
5
但是,在空白的deinit
方法中,NO 断点永远不会被击中:
1
2 deinit {
3
4 }
5
通过添加更多的代码行,我们可以看到它取决于断点后面是否有可执行的代码行:
➤ 1
➤ 2 deinit {
➤ 3 //
➤ 4 doNothing()
➤ 5 //
➤ 6 foo = "abc"
7 //
8 }
9
尤其要密切注意第 7 行和第 8 行,因为这与 doNothing()
的行为有很大不同!
如果您习惯了第 4 行的断点在 doNothing()
中的工作方式,您可能会错误地推断如果您只有第 5 行的断点(甚至 4) 在这个例子中:
➤ 1
➤ 2 deinit {
➤ 3 number++
4 // incrementNumber()
5 }
6
注意:对于在同一行暂停执行的断点,它们会按照创建的顺序命中。为了测试他们的订单,我将断点设置为记录消息并在评估操作后自动继续。
注意:在我的测试中,还有另一个潜在的陷阱可能会让您陷入困境:如果您使用 print("test")
,它会弹出调试区向您显示消息(消息以粗体显示)。但是,如果您添加断点并告诉它Log Message,它会以常规文本记录它并且不会弹出打开调试区。您必须手动打开调试区才能看到输出。
注意:这都是在 Xcode 7.1.1 中测试的
关于ios - Deinit 未在 UIViewController 上调用,但 Dealloc 是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33112147/