ARC doesn't work?

I have worked with Swift book, example with using a weak reference to avoid strong reference cycles.

This is an example from the book. The issue that after setting john to nil the object should be deallocated and deinit should print

"John Appleseed is being deallocated".

But it doesn't work. I have an impression that despite weak reference Person object is still in memory. Is this Swift bug?

   class Person {
      let name: String
      init(name: String) { self.name = name }
      
      var apartment: Apartment?
      
      deinit { print("\(name) is being deallocated.")  }
    }

    class Apartment {
      let unit: String
      init(unit: String) { self.unit = unit }
      
      weak var tenant: Person?
      
      deinit { print("Apartment \(unit) is being deallocated.") }
    }

    var john: Person?
    var unit4A: Apartment?

    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")

    john!.apartment = unit4A
    unit4A!.tenant = john

    john = nil

Hello,

Do you run your code in an Xcode Playground? Because playgrounds keep values alive, and alter the behavior you would witness in a "real" application.

(I have a hard time finding a reference for this online).

3 Likes

Yes, I run an example in the playground, Swift book recommends using the playground for experiments with Swift :)

Thank you for your reply!

You could use Xcode > New > Project > macOS > Command Line Tool and try the code there, especially for memory allocation related stuff.

1 Like

Yes, with Command Line Tool all is working as intended.
Thank you for advice!

If you using playground to test ARC, you can simply put all the code inside do { /* code here */ }

5 Likes

Unfortunately, the approach with do block doesn't work with weak references. Playground somehow doesn't deallocate objects with reference cycle even with using weak. The sample of the code below, please verify.

class Person {
  let name: String
  init(name: String) { self.name = name }
  
  var apartment: Apartment?
  
  deinit { print("\(name) is being deallocated.")  }
}

class Apartment {
  let unit: String
  init(unit: String) { self.unit = unit }
  
  weak var tenant: Person?
  
  deinit { print("Apartment \(unit) is being deallocated.") }
}


do {
  var john: Person?
  var unit4A: Apartment?

  john = Person(name: "John Appleseed")
  unit4A = Apartment(unit: "4A")

  john!.apartment = unit4A
  unit4A!.tenant = john

  john = nil
}

I got this result

Thank you for the response. I see a different picture.
Weird behavior of playground. Also found a similar thread on StackOverflow. https://stackoverflow.com/questions/24082011/weak-references-in-swift-playground-dont-work-as-expected

I never seen this before. That’s odd.

Can you try macOS mode with the playground?
I want to know is it the case.

I have created a new playground with macOS mode but have the same result. deinit not called.