这是我的测试代码(在终端中运行):
#!/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()
解决方法
虽然我没有看到一个明确的引用说“Swift的deinit与ObjC的dealloc具有完全相同的语义”,但很难想象这不是真的,因为Swift和ObjC对象都由ARC管理,一般来说可以互换.
鉴于此,这是完全可以预期的. Cocoa在程序终止时不会释放对象.它只是终止,泄漏所有内存,文件句柄和其他系统资源,并将其留给操作系统进行清理.这使程序终止速度明显快于其他情况.
这是一个重要的观点,因为这意味着您通常不应该使用deinit来管理除OS管理的资源之外的任何内容(当然不是您需要运行的任何内容).当然,即使在C中,也无法保证析构函数运行.如果你崩溃了,它就不会发生,你的程序将不得不处理它.您可以将其想象为所有Cocoa程序在终止时悄然崩溃.
所以在你的情况下,a = nil会导致deinit运行,而程序终止则不会.