繁体   English   中英

Deinit没有调用UIViewController,但是Dealloc是

[英]Deinit not called on a UIViewController, but Dealloc is

似乎deinit相当于deallocdeinit 但是,当您尝试在UIViewController上定义方法时,它的行为并不像您期望的那样......

建立

  1. 使用Swift或Objective-C中的Xcode 7.0创建一个新的Single View项目。
  2. 在使用storyboard创建的视图控制器上添加“dismiss”按钮(我将此视图控制器称为VC2;其类为ViewController)。
  3. 添加一个新的视图控制器并将其设置为初始视图控制器(VC1,类为零)。
  4. 向VC1添加“present”按钮,其中“Present Modally”segue到VC2。
  5. 在VC2的代码中,在deinit (Swift)或dealloc (Objective-C)中放置一个断点。
  6. 在VC2中,使“解除”按钮的操作执行以下操作:

     // Swift: presentingViewController?.dismissViewControllerAnimated(true, completion: nil) // Objective-C: [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 
  7. 运行应用程序并点击两个按钮以首先显示VC2,然后将其关闭。

注意在Objective-C中 ,如何命中dealloc断点

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

为什么deinit从未被叫过? 这是一个bug还是设计?

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


注意:如果您尝试在Swift中定义dealloc方法,则会收到以下错误:

使用Objective-C选择器'dealloc'的方法'dealloc()'与使用相同Objective-C选择器的deinitializer冲突。

如果你有斯威夫特视图控制器从一个Objective-C控制器继承,你把一个断点在Objective-C的dealloc方法,您将获得上述相同的错误行为:在deinit不会被调用,而dealloc会调用。

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

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

TLDR:

如果前面有可执行的代码行,断点将仅在deinitdeinit

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

感谢Adam让我指出了正确的方向 我没有做广泛的测试,但它看起来像断点行为不同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

注意:对于在同一行上暂停执行的断点,它们将按创建顺序命中。 为了测试他们的顺序,我设置了一个断点到Log Message在评估操作后自动继续

注意:在我的测试中还有另一个潜在的陷阱可能会让你:如果你使用print("test") ,它会弹出Debug Area来显示消息(消息以粗体显示)。 但是,如果添加断点并将其告诉Log Message ,它将以常规文本记录它,而不是弹出打开调试区域。 您必须手动打开调试区域才能看到输出。

注意:这都在Xcode 7.1.1中进行了测试

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

看起来函数不会被调用,除非一些代码被放入deinit(怪异)必须是swift的优化阶段的一部分。

尝试按照建议在您的deinit中放置打印声明并报告您的发现

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM