1

I was playing with unowned references. As I understood from the WWDC videos, unowned references can't be nil, and they do not increase the retain count of whatever object they reference. I thought that if an unowned reference is deallocated, then the object that held the unowned reference is also deallocated.

Consider the following code:

class Parent {
    var child : Child?

    func foo() {
        println("Hello")
    }
}

class Child {
    unowned let parent : Parent

    init(parent: Parent) {
        self.parent = parent
    }
}

var parent : Parent? = Parent()
parent!.child = Child(parent: parent!)

weak var child = parent!.child

parent = nil

child!.parent.foo()

This code works! How come child exists, and moreover, how come parent apparently still exists? I had thought that after setting parent = nil, child would also be nil. It seems as if the unowned reference is acting as if it were a strong reference.

Any ideas as to why this code works?

Cezary Wojcik
  • 21,745
  • 6
  • 36
  • 36
  • Its not going to be released at the exact point you set `parent=nil`, it will most likely be released after you exit the current scope, but I believe that is not guaranteed either. Also, `weak` is what you should use if you hope for it to be `nil`'ed out after its deallocated. `unowned` has slightly different behaviour – Jack Jun 09 '14 at 21:41
  • @JackWu: "Its not going to be released at the exact point you set parent=nil" It could be. – newacct Jun 10 '14 at 21:08
  • "This code works!" It's undefined behavior. Anything can happen. Just because it seems to produce the right output in this case does not mean that it "works". Sending a message to a deallocated object often does not "crash". And an object is not guaranteed to be deallocated just because you don't have any strong references to it (e.g. it could have been autoreleased). – newacct Jun 10 '14 at 21:09

1 Answers1

3

Your code will most likely only work in the playground, where the memory management is a little... fuzzy.

When I ran this in Xcode, it crashes as you'd expect. The playground is meant to make it easy to test the syntax, play with some classes, etc. It's not the best place to play around with weak/unretained variables.

I haven't found any documented sources describing how exactly the memory is managed in a playground, but it's definitely different from how it will be in an actual runtime.

Craig Otis
  • 31,257
  • 32
  • 136
  • 234
  • Gah... This isn't the first time that I've wrongly assumed that Playground and "real" Swift behave the same way. I'm going to write up a bug report. Thanks! – Cezary Wojcik Jun 09 '14 at 22:05
  • Yeah, the playground [definitely seems to keep hold of variables itself](http://stackoverflow.com/a/24021446/300836), so it's not the best place to test deallocation. – Matt Gibson Jun 10 '14 at 06:51