Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weak references in Swift playground don't work as expected

Tags:

swift

I have been following the weak referencing example from the Intermediate Swift WWDC session in a Playground. I modified the code slightly as follows:

class Apartment {
    let address: Int

    init(address: Int) {
        self.address = address
    }

    weak var tenant: Person?
}

class Person {
    let name: String

    init(name: String){
        self.name = name
    }

    weak var home: Apartment?

    func moveIn(apt: Apartment) {
        self.home = apt
        apt.tenant = self
    }
}

var renters = ["John Appleseed": Person(name: "John Appleseed")]
var apts = [16: Apartment(address: 16)]

renters["John Appleseed"]!.moveIn(apts[16]!)
renters["John Appleseed"] = nil // memory should be released here

// then apts[16].tenant should be nil
if let tenantName = apts[16]!.tenant?.name {
    // this should only execute if the Person object is still in memory
    println("\(tenantName) lives at apartment number \(apts[16]!.address)")
} else {
    // and this line should execute if the memory is released as we expect
    println("Nobody lives at apartment number \(apts[16]!.address)")
}

// Console output in Playground: John Appleseed lives at apartment number 16
// Console output in standalone app: Nobody lives at apartment number 16

From my understanding of weak referencing, the memory allocated for the instance of Person should be released when it is removed from the renters dictionary because the only other reference to it is weak. However, the output of the programme is different if it is run as a standalone command line application vs. in a Playground (see comments).

like image 892
Anton Tcholakov Avatar asked Jun 06 '14 12:06

Anton Tcholakov


People also ask

Does weak can be make as strong property in any case in Swift?

A weak property must be an optional, as well. Otherwise it cannot be nil. An instance's retain count is not affected by a weak reference, as opposed to a strong reference. Beyond an instance's existing retain count, a weak reference does not keep the instance in memory.

What is weak reference in Swift?

Weak References in Swift A weak reference does not increment or decrement the reference count of an object. Since weak references do not increment the reference count of an object, a weak reference can be nil . This is because the object could be deallocated while the weak reference is pointing to it.

What is difference between weak and strong in Swift?

For example, a strong reference keeps a firm hold on instances and doesn't allow deallocation by ARC. Similarly, a weak reference cannot protect the instances from being deallocated by ARC. Before you learn about strong and weak reference, make sure to understand how classes and objects work in Swift.


2 Answers

I believe the top-level function (REPL/playground) is keeping a strong reference to facilitate interactive behavior, and cleaning up when the frame returns. This behavior eliminates memory leaks in the interactive environment.

I copied Viktor's simple example and used the xcrun swift REPL.

In REPL mode, I wrapped the logic in a function and it works as expected. If/when you care when the memory is cleaned up, I would suggest wrapping your logic in a function.

// declaration of the types
class Person {
   let name: String
   weak var home: Apartment?

  init(pName: String){
      name = pName
  }

}

class Apartment {
    let postalCode: Int

    init(pPostalCode: Int) {
        postalCode = pPostalCode
    }
}

func testArc() {
    // create Person object
    var personJulius: Person = Person(pName: "Julius")

    // create Apartment object
    var apartmentBerlin: Apartment? = Apartment(pPostalCode: 10777)

    // connect Apartment object and Person object
    personJulius.home = apartmentBerlin

    // Set only strong reference of Apartment object to nil
    apartmentBerlin = nil

    // Person object should now have nil as home
    if personJulius.home != nil {
        println("Julius does live in a destroyed apartment")
    } else {
        println("everything as it should")
    }

}

//outputs "everything as it should"
testArc()
like image 188
wbennett Avatar answered Sep 21 '22 07:09

wbennett


I guess that the Playground itself keeps a strong reference to the object, so the code behaves differently? If that's the case, this could cause some unexpected problems!

like image 26
Anton Tcholakov Avatar answered Sep 19 '22 07:09

Anton Tcholakov