当前位置 : 主页 > 手机开发 > 其它 >

macos – Swift:在deinit方法中没有println的输出(不使用playground)

来源:互联网 收集:自由互联 发布时间:2021-06-11
这是我的测试代码(在终端中运行): #!/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运行,而程序终止则不会.

网友评论