Swift playground中的弱引用无法按预期工作

Ant*_*kov 9 swift

我一直在Playground中的中级Swift WWDC会话中关注弱引用示例.我稍微修改了代码如下:

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
Run Code Online (Sandbox Code Playgroud)

根据我对弱引用的理解,当从renters字典中删除时,应该释放为Person实例分配的内存,因为对它的唯一其他引用很弱.但是,如果程序作为独立命令行应用程序而不是Playground运行,则程序的输出会有所不同(请参阅注释).

wbe*_*ett 5

我相信顶级函数(REPL/playground)保持强大的参考,以促进交互行为,并在帧返回时进行清理.此行为消除了交互式环境中的内存泄漏.

我复制了Viktor的简单示例并使用了xcrun swiftREPL.

在REPL模式下,我将逻辑包装在一个函数中,它按预期工作.如果/当你关心内存被清理时,我会建议将你的逻辑包装在一个函数中.

// 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()
Run Code Online (Sandbox Code Playgroud)


Ant*_*kov 2

我猜 Playground 本身保留了对该对象的强引用,因此代码的行为有所不同?如果是这样的话,可能会导致一些意想不到的问题!