Deinit没有调用UIViewController,但是Dealloc是 [英] Deinit not called on a UIViewController, but Dealloc is

查看:274
本文介绍了Deinit没有调用UIViewController,但是Dealloc是的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看起来像Swift相当于 dealloc DEINIT 。但是,当您尝试在UIViewController上定义方法时,它的行为并不像您期望的那样...

It seems like the Swift equivalent of dealloc is deinit. However, when you attempt to define the method on a UIViewController, it doesn't behave as you would expect...

设置


  1. 使用Xcode 7.0在Swift或Objective-C中创建一个新的Single View项目。

  2. 添加用storyboard创建的视图控制器上的dismiss按钮(我将这个视图控制器称为VC2;它的类是ViewController)。

  3. 添加一个新的视图控制器和将其设置为初始视图控制器(VC1,类为零)。

  4. 向VC1添加一个当前按钮,其中当前模态字节为VC2。

  5. 在VC2的代码中,在<$中放置一个断点c $ c> deinit (Swift)或 dealloc (Objective-C)。

  6. 在VC2中,使解除按钮的操作执行以下操作:

  1. Create a new Single View project using Xcode 7.0, in either Swift or Objective-C.
  2. Add a "dismiss" button on the view controller that was created with the storyboard (I'll refer to this view controller as VC2; its class is ViewController).
  3. Add a new view controller and set it to be the initial view controller (VC1, class is nil).
  4. Add a "present" button to VC1 with a "Present Modally" segue to VC2.
  5. In VC2's code, put a breakpoint in deinit (Swift) or dealloc (Objective-C).
  6. In VC2, make the "dismiss" button's action do the following:

// Swift:
presentingViewController?.dismissViewControllerAnimated(true, completion: nil)

// Objective-C:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];


  • 运行应用程序并点击两个按钮以首先显示VC2,然后将其关闭。

  • 请注意 Objective-C dealloc 断点被击中

    Notice how in Objective-C, the dealloc breakpoint is hit.

    另一方面,在 Swift deinit 断点从未被击中

    In Swift, on the other hand, the deinit breakpoint is never hit.

    为什么 deinit never叫?这是一个错误还是设计?

    Why is deinit never called? Is this a bug or by design?

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

    If this is by design, where should I put clean up code to free up resources when the view controller will no longer be needed? (It can't be in viewDidUnload since that method is deprecated. It can't be in viewDidDisappear because something else might be holding a reference to it and will eventually show it again.)

    注意:如果您尝试定义<在Swift中code> dealloc 方法,你得到以下错误:

    Note: If you attempt to define a dealloc method in Swift, you get the following error:


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

    Method 'dealloc()' with Objective-C selector 'dealloc' conflicts with deinitializer with the same Objective-C selector.

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

    If you have the Swift view controller inherit from an Objective-C controller, and you put a breakpoint in the Objective-C dealloc method, you will get the same buggy behavior defined above: the deinit will not be called, but the dealloc will be called.

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

    If you attempt to use Allocations to view the number of instances of the class in memory, both versions show the same thing: The # Persistent is always 1, and the # Transient increases each time you show the second view controller.

    鉴于上述设置,应该没有强力参考循环保持视图控制器。

    Given the above setup, there should be no strong reference cycle holding on to the view controller.

    推荐答案

    TLDR:


    • 如果在一行可执行代码上放置断点,那么它将起作用。

    • 可执行代码行必须属于 deinit 方法。

    • If you place a breakpoint on a line of executable code, then it will work.
    • The executable line of code must belong to the deinit method.

    感谢 Adam让我指向正确的方向。我没有进行大量测试,但看起来断点在 deinit 中的行为与代码中的其他地方不同。

    Thanks to Adam for pointing me in the right direction. I didn't do extensive tests, but it looks like breakpoints behave differently in deinit than everywhere else in your code.

    我将向您展示几个例子,其中我在每个行号上添加了一个断点。那些将起作用的(例如暂停执行或执行他们的操作,如记录消息)将通过➤符号表示。

    I will show you several examples where I added a breakpoint on each line number. Those that will work (e.g. pause execution or perform their action such as logging a message) will be indicated via the ➤ symbol.

    通常断点被大量击中,即使方法无效:

    Normally breakpoints are hit liberally, even if a method does nothing:

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

    但是,空白 deinit 方法,断点将被击中:

    However, in a blank deinit method, NO breakpoints will ever get hit:

      1
      2  deinit {
      3 
      4  }
      5
    

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

    By adding more lines of code, we can see that it depends on if there is an executable line of code following the breakpoint:

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

    特别要密切注意第7和第8行,因为这显着不同从如何 doNothing()表现出来!

    In particular, play close attention to lines 7 and 8, since this differs significantly from how doNothing() behaved!

    如果你已经习惯了第4行断点的工作方式在 doNothing()中,如果在此示例中第5行(甚至4)只有断点,则可能会错误地推断出您的代码没有执行:

    If you got used to this behavior of how the breakpoint on line 4 worked in doNothing(), you may incorrectly deduce that your code is not executing if you only had a breakpoint on line 5 (or even 4) in this example:

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

    注意:对于暂停执行的断点它们按照创建顺序命中。为了测试他们的订单,我设置了一个断点到日志消息评估行动后自动继续

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

    Note: In my testing there was also another potential pitfall that might get you: If you use print("test"), it will pop up the Debug Area to show you the message (the message appears in bold). However, if you add a breakpoint and tell it to Log Message, it will log it in regular text and not pop open the Debug Area. You have to manually open up the Debug Area to see the output.

    注意:这都在Xcode 7.1.1

    这篇关于Deinit没有调用UIViewController,但是Dealloc是的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆