【问题标题】:Swift Deinitialization of Globals全局变量的快速去初始化
【发布时间】:2014-07-12 04:13:12
【问题描述】:

我的 Swift 全局变量没有被取消初始化。

class Person {
  let name: String
  init(name: String) {
    self.name = name
    println("\(name) is being initialized")
  }
  deinit {
    println("\(name) is being deinitialized")
  }
}

func local() {
  let person = Person(name: "Local")
}

local()

var personp: Person? = Person(name: "Optional Global")
personp = nil

var person = Person(name: "Global")

我使用 Xcode6-Beta3 在禁用优化的独立二进制文件中运行它(因为 apparently the playground has issues with deinit):

> xcrun swift -O0 arc.swift && ./arc
Local is being initialized
Local is being deinitialized
Optional Global is being initialized
Optional Global is being deinitialized
Global is being initialized

请注意缺少的全局正在被取消初始化

我什至无法弄清楚这是预期的行为还是错误,所以如果是前者,那么对相关法律术语的引用将不胜感激。

【问题讨论】:

  • 为什么要重新初始化全局?它实际上是一个属性,不是吗?
  • 当前的两个答案都提到,鉴于底层实现,这并非完全出乎意料。正如我在问题中所说,如果是这种情况,那么我希望得到更明确的引用。这是一个问题的原因是全局可能正在跟踪某种资源(文件、数据库连接等),并且鉴于当前的行为,程序员有责任确保不保留这样的“资源所有者”作为全球性的。

标签: ios swift


【解决方案1】:

对我来说看起来不错...在结束应用程序时没有释放任何内容 - 没有意义


deinit 仅用于释放内存并删除观察者和其他东西 - 在结束进程时,这有点“无用”,因为进程内存无论如何都会“被擦除”

==>

所以:

除了内存管理/观察者相关的东西之外,不要在 deinit 中添加任何东西

如果您需要一个专用的停止方法 - 编写一个并在退出进程之前显式调用它

【讨论】:

  • 我同意 - 似乎如果我们依赖于调用它们的 deinit,我们不应该将任何“资源所有者”保留为全局对象。不过,我有点希望引用:),因为并非所有语言都如此。例如,C++(似乎是对 Swift 的影响之一)确实为全局对象调用了析构函数。
【解决方案2】:

把最后一行代码想象成:

var personp: Person? = Person(name: "Optional Global")
personp = nil

var person = Person(name: "Global")

exit(0)

由于person 从未设置为其他值,ARC 不会在退出前减少保留计数。

Swift 像 C 程序一样工作,执行只是终止,然后所有分配给进程的内存在一次扫描中返回。

这与依赖进程内事件来释放内存的执行中内存处理非常不同。由于程序的所有执行已经完全停止,所以没有线程可以运行deinit

总之,这是应该的。

【讨论】:

  • 由于 Swift 被认为使用起来更加安全,因此可以合理地期望它在(常规)终止之前运行反初始化程序。 (当然,如果你kill -9 什么都做不了。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
  • 1970-01-01
  • 1970-01-01
  • 2015-07-18
相关资源
最近更新 更多