6

ARC object deletion seems to be inconsistent in the Swift Playground. Is it a bug or by design?

Consider this class:

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

When I call it from the playground (not the command line REPL, see comment below):

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

I see only initialization messages in the console:

t1 initialized
t2 initialized

What's missing is deinit of t2.

When I run it in an app (e.g. entry of app delegate), I the output is consistent with ARC deletion (i.e. t1 init, then t2, and t2 deinit and then t1, since the entire invocation block goes out of scope):

t1 initialized
t2 initialized
t2 deinitialized
t1 deinitialized

Finally, in the command line REPL (see comment below for accessing the REPL), the results are consisent, i.e.: t1 is alive due to its top level scope, but t2 is ARC deleted, as one would expect.

  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
Venkat Peri
  • 1,744
  • 3
  • 16
  • 20
  • *Is it a bug or by design?* Impossible to know for sure. If you think it's a bug, you should by all means file a bug report. But since the playground is interactive in nature, it stands to reason that it might keep any created objects around. More to the point, don't expect the lifetime of an object in the playground to exactly match the lifetime in an app. – Caleb Jun 03 '14 at 17:29
  • 1
    BTW, the Playground and the REPL aren't the same thing - you can get to the REPL by typing "repl" at the lldb debugger prompt while debugging, or at the command line via these commands: http://stackoverflow.com/a/24011715/59541 – Nate Cook Jun 03 '14 at 17:41
  • I have the same issue, can't test object deinitialization in playground as I learn the language in the book, sad but true. – Giovanni Silva Jul 19 '14 at 20:12

2 Answers2

5

We compared ARC/deletion of objection in an app scenario and within the Playground. Our test code used object created inside and outside a particular scope. We also nested the tester object to test multi-nested scoping.

We saw that the app scenario deletes objects right on cue (zeroth reference) whereas the Playground scenario deletes a few, but holds on to a majority of objects (irrespective of scope, but apparently consistent over multiple runs).

The Playground probably holds on to objects in order to service its assistant GUI output (and/or its playback feature).

See blog post here .

mfaani
  • 33,269
  • 19
  • 164
  • 293
Venkat Peri
  • 1,744
  • 3
  • 16
  • 20
4

I found that I could trigger the call to deinit{} in a playground (Xcode version 6.0 (6A313)) by adding an outer layer of optional:

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

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

which creates this output:

t3 initialized
t3 deinitialized
Armorix
  • 41
  • 2
  • 2