Memory leaks in the swift playground / deinit{} not called consistently
ios, swift
Solution
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 .
Problem
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 ```