swift playground / deinit 中的内存泄漏未一致调用

Posted

技术标签:

【中文标题】swift playground / deinit 中的内存泄漏未一致调用【英文标题】:Memory leaks in the swift playground / deinit not called consistentlyswift playground / deinit 中的内存泄漏未一致调用 【发布时间】:2014-06-03 17:24:56 【问题描述】:

ARC 对象删除在 Swift Playground 中似乎不一致。这是一个错误还是设计使然?

考虑这个类:

class Test 
  var name: String
  init(name:String)
    self.name = name
    println("\(name) initialized")
  
  deinit
    println("\(name) deinitialized")
  

当我从操场调用它时(不是命令行 REPL,请参阅下面的评论):

var t1 = Test(name: "t1")
var t2 : Test? = Test(name: "t2")
t2 = nil

我在控制台中只看到初始化消息:

t1 initialized
t2 initialized

缺少的是 t2 的 deinit。

当我在应用程序中运行它时(例如应用程序委托的条目),我的输出与 ARC 删除一致(即 t1 init,然后 t2,以及 t2 deinit 然后 t1,因为整个调用块超出了范围):

t1 initialized
t2 initialized
t2 deinitialized
t1 deinitialized

最后,在命令行 REPL(请参阅下面的评论以访问 REPL)中,结果是一致的,即:t1 由于其***范围而处于活动状态,但正如人们所期望的那样,t2 被 ARC 删除。

  1> class Test 
  2.       var name: String
  3.       init(name:String)
  4.               self.name = name
  5.               println("\(name) initialized")
  6.       
  7.       deinit
  8.               println("\(name) deinitialized")
  9.       
 10. 
 11> var t1 = Test(name: "t1")
t1 initialized
t1 initialized
t1 deinitialized
t1: Test = 
  name = "t1"

 12> var t2 : Test? = Test(name: "t2")
t2 initialized
t2 initialized
t2 deinitialized
t2: Test? = (name = "t2")
 13> t2 = nil
t2 deinitialized
 14> t1
$R2: Test = 
  name = "t1"

 15> t2
$R3: Test? = nil

【问题讨论】:

这是一个错误还是设计使然? 无法确定。如果你认为这是一个错误,你应该提交一份错误报告。但是由于操场本质上是交互式的,因此它可以保留任何创建的对象。更重要的是,不要期望 Playground 中对象的生命周期与应用中的生命周期完全匹配。 顺便说一句,Playground 和 REPL 不是一回事 - 您可以在调试时在 lldb 调试器提示符下输入“repl”,或者通过以下命令在命令行中输入“repl”: ***.com/a/24011715/59541 我有同样的问题,当我学习书中的语言时,无法在操场上测试对象取消初始化,悲伤但真实。 【参考方案1】:

我们在应用场景和 Playground 中比较了 ARC/删除反对。我们的测试代码使用了在特定范围内外创建的对象。我们还嵌套了 tester 对象来测试多嵌套范围。

我们看到应用场景在提示时删除了对象(第零个引用),而 Playground 场景删除了一些对象,但保留了 大多数 对象(无论范围如何,但显然一致多次运行)。

Playground 可能会保留对象以服务其辅助 GUI 输出(和/或其播放功能)。

见博文here。

【讨论】:

您在博客上发布的代码在此行出现错误activeObjects = uuid【参考方案2】:

我发现我可以在 Playground(Xcode 版本 6.0 (6A313))中通过添加 optional 的外层来触发对 deinit 的调用:

struct MetaTest 
   var t3: Test? = Test(name: "t3")


var mt3: MetaTest? = MetaTest()
mt3!.t3 = nil

创建此输出:

t3 initialized
t3 deinitialized

【讨论】:

以上是关于swift playground / deinit 中的内存泄漏未一致调用的主要内容,如果未能解决你的问题,请参考以下文章

是否应该重写 deinit 以删除 Swift 中的观察者?

为 NSNotificationCenter = Swift deinit() 调用 .removeObserver 的正确位置?

iOS swift:Deinit一个孩子View Controller

初尝Swift-用Playground来学习Swift语言

Swift 中 Playgrounds 的用途是啥?

如何将数据从 Playground 页面传递到 Swift Playgrounds 中的另一个 Playground 页面?