Swift 操场中的弱引用无法按预期工作
我一直在 Playground 中关注 Intermediate Swift WWDC session 中的弱引用示例.我稍微修改了代码如下:
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
根据我对弱引用的理解,为 Person 实例分配的内存应该在从租用者字典中删除时释放,因为对它的唯一其他引用是弱引用.但是,如果程序作为独立命令行应用程序运行与在 Playground 中运行,则该程序的输出是不同的(请参阅评论).
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).
我相信顶级函数 (REPL/playground) 会保持强引用以促进交互行为,并在帧返回时进行清理.此行为消除了交互环境中的内存泄漏.
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.
我复制了 Viktor 的简单示例并使用了 xcrun swift
REPL.
I copied Viktor's simple example and used the xcrun swift
REPL.
在 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()