这是我的测试代码(在终端中运行): #!/usr/bin/xcrun swiftvar count = 0; // for reference countingclass A { init() { count++; } deinit { println("A deinit") count--; }}var a: A? = A()println(count)a = nil // no output if I comme
#!/usr/bin/xcrun swift
var count = 0; // for reference counting
class A {
init() {
count++;
}
deinit {
println("A deinit")
count--;
}
}
var a: A? = A()
println(count)
a = nil // no output if I comment out this statement
println(count)
输出:
1 A deinit 0
如果上面提到的行被注释掉,则没有输出“A deinit”.输出将是:
1 1
我用swiftc编译代码但结果仍然相同. (xcrun swiftc -o test test.swift)
通过设计,当程序退出时,stdout将被关闭,或者当它们被破坏时,对象仍被引用(通过什么?)?
更新:感谢@Logan,现在我有更多关于它的细节.
当它在函数内部运行时,即使我注释掉a = nil,它也会输出A deinit:
#!/usr/bin/xcrun swift
class A {
deinit {
println("A deinit")
}
}
func test() {
var a: A? = A()
//a = nil
}
test()
我没有在Xcode中使用游乐场. : – $
更新
#!/usr/bin/xcrun swift
import Foundation
class A {
deinit {
var s = "A deinit"
println(s)
var a: A? = A()
a = nil
var error: NSError?
var path = "\(NSFileManager.defaultManager().currentDirectoryPath)/swift_test.txt"
if s.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding, error: &error) {
println("File saved at \(path)")
} else {
println(error)
}
}
}
//func test() {
var a: A? = A()
//}
//test()
结果:除非在测试函数中运行,否则不输出到stdout或文件.
虽然我没有看到一个明确的引用说“Swift的deinit与ObjC的dealloc具有完全相同的语义”,但很难想象这不是真的,因为Swift和ObjC对象都由ARC管理,一般来说可以互换.鉴于此,这是完全可以预期的. Cocoa在程序终止时不会释放对象.它只是终止,泄漏所有内存,文件句柄和其他系统资源,并将其留给操作系统进行清理.这使程序终止速度明显快于其他情况.
这是一个重要的观点,因为这意味着您通常不应该使用deinit来管理除OS管理的资源之外的任何内容(当然不是您需要运行的任何内容).当然,即使在C中,也无法保证析构函数运行.如果你崩溃了,它就不会发生,你的程序将不得不处理它.您可以将其想象为所有Cocoa程序在终止时悄然崩溃.
所以在你的情况下,a = nil会导致deinit运行,而程序终止则不会.
