在一个应用程序中,我想知道为什么在退出应用程序时没有调用类的deinit
方法的实例。
举个例子,这里介绍的Test类是在AppDelegate的applicationDidFinishLaunching
中创建的。
import Cocoa
class Test {
let testVar = 1
init() {
print("Retain count \(CFGetRetainCount(self))")
NSApplication.shared().terminate(self)
}
deinit {
print("Calling deinit")
}
}
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
//@IBOutlet weak var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
_ = Test()
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
print("Terminating")
}
}
这不仅无法调用Test的deinit
方法,而且Test init
中的保留计数为2;我原以为这是1。
如果可选引用存储在AppDelegate类中并在创建Test实例时设置,则在调用applicationWillTerminate
时为nil
有人可以在这里解释为什么保留计数为2以及如何确保在应用程序终止时调用Test的deinit?
答案 0 :(得分:1)
我无法说明为什么保留计数为2.一般来说,启用ARC后,你真的不应该检查保留计数,原因是well answered question < / p>
此外,还有answer表示CFGetRetainCount
实际上可能会在您调用时增加保留计数。
在您的情况下,deinit
未被调用,因为您在初始化程序完成之前以编程方式终止应用程序。
如果Test
上的变量已分配AppDelegate
,则deinit
未调用AppDelegate
,因为nil
未在&#34中发布;正常&#34;应用程序退出时的方式。因此,它的所有属性都不会被释放。如果您在applicationWillTerminate
中将变量设置为deinit
,那么您会看到class Test {
let testVar = 1
init() {
print("Retain count \(CFGetRetainCount(self))")
}
deinit {
print("Calling deinit")
}
}
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var variable: Test?
func applicationDidFinishLaunching(_ aNotification: Notification) {
variable = Test()
DispatchQueue.global().asyncAfter(deadline: .now() + 1.0) {
// If you're trying to pass in `variable`, the terminate funciton will retain it
NSApplication.shared.terminate(nil)
}
}
func applicationWillTerminate(_ aNotification: Notification) {
variable = nil
}
}
被恰当地调用。在this answer中讨论全局变量时,会解释此行为。
提供您提供的示例的特定排列:
deinit
如果实例是由ARC发布的,那么 CFGetRetainCount
只能被保证被调用,但是如果从未调用过版本,例如,如果应用程序崩溃或被用户强行使用它就不会被所以,不要依赖它来绝对批判&#34;清理&#34;。
重新考虑保留计数。您的代码完全按照您的问题执行,产生以下内容:
我们所看到的是保留计数在调用terminate
期间递增1,然后在返回时递减,然后在它传递给{{时再次递增1}}。
答案 1 :(得分:1)
我认为Swift情况与此链接中记录的Objective-C相同: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH
&#34;当应用程序终止时,可能不会向对象发送dealloc消息。因为进程的内存在退出时自动清除,所以只是允许操作系统清理资源比调用所有内存管理方法更有效。&#34;
答案 2 :(得分:0)
问题是由于init
类Test
内的应用程序终止。我怀疑在terminate
中调用init
会阻止正确实例化类,因此永远不会调用它deinit
。
通过延迟拨打terminate
,可以按预期调用对测试版deinit
的调用
import Cocoa
class Test {
init() {
DispatchQueue.global().asyncAfter(deadline: .now() + 1.0) {
NSApplication.shared().terminate(self)
}
}
deinit {
print ("Calling Deinit")
}
}
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
//@IBOutlet weak var window: NSWindow!
var variable: Test?
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
variable = Test()
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
variable = nil
print("Terminating")
}
}