在特定情况下不调用 deinit

deinit not called in specific case

我有以下测试用例:我希望 deinit 在程序终止时被调用,但它从来没有。我是 Swift 的新手,但不认为这是预期的行为。 (这不是在操场上)

class Test
{
   init() {
      print( "init" )
   }

   deinit {
      print( "deinit" )
   }
}

print("Starting app")

var test = Test()

print( "Ending App" )

输出是:

Starting app
init
Ending App
Program ended with exit code: 0

如果我将代码放在一个函数中,然后调用该函数,我会得到预期的结果

Starting app
init
Ending App
deinit
Program ended with exit code: 0

不应该在程序终止时调用对象的 deinit 吗?

There是一个类似的问题。

Apple 没有明确解释 deinit 的工作原理。当 class 正在释放时,它通过 ARC 调用。我认为当应用程序终止时,与 class 的常规运行时取消初始化相比,有不同的取消初始化机制。或者也许主要 window 保留您的 class?无论如何,为了在应用程序终止时执行代码,您应该使用应用程序委托(如 applicationWillTerminate)。

I expect deinit to be called at program termination

你不应该期望那样。程序终止时存在的对象通常不会被释放。内存清理留给操作系统(它释放所有程序的内存)。这是 Cocoa 中的 long-existing 优化,以加速程序终止。

deinit 仅用于释放资源(例如释放不在 ARC 下的内存)。在 ObjC 或 Swift 中没有等效的 C++ 析构函数。 (C++ 和 Objective-C++ 对象在程序终止期间被销毁,因为这是规范所要求的。)

If I place the code in a function and then call the function I get expected results

是的,这是可行的,因为 test 变量的生命周期由方法的范围定义。当方法的范围结束时(即方法从 Stack 中删除),所有局部变量的生命都将结束,除非对这些变量有其他强引用。

Shouldn't deinit of the object be called at program termination

无法像 Android 那样以编程方式在 iOS 中优雅地关闭应用程序。关闭应用程序的可能方式是,

  1. 通过从最近的应用程序列表向上滑动(终止)
  2. 或者故意撞车
  3. 或者让 OS 由于 low-memory 原因终止您的应用程序。

您的应用程序的所有内存都将在 OS 终止时被清除,因此 deinit 不会被调用,我们也不能期望如此。你可以注意到 termination 这个词,它解释了程序没有以正确的方式结束的事实,所以我们不能指望 OS 做最后的荣誉.