我希望以编程方式创建(和销毁)NSWindows
class Wins: NSObject, NSWindowDelegate {
var windows = Set<NSWindow>()
func createWindow() {
let newWindow = NSWindow(contentRect: .init(origin: .zero, size: .init(width: 300, height: 300)),
styleMask: NSWindow.StyleMask(rawValue: 0xf),
backing: .buffered,
defer: false)
newWindow.title = "New Window"
newWindow.isOpaque = false
newWindow.isMovableByWindowBackground = true
newWindow.backgroundColor = NSColor(calibratedHue: 0, saturation: 1.0, brightness: 0, alpha: 0.7)
newWindow.makeKeyAndOrderFront(nil)
let windowController = NSWindowController()
windowController.window = newWindow
windows.insert(newWindow)
}
func closeAll() {
for win in windows {
windows.remove(win)
win.close()
}
}
}
虽然上面的代码可以工作,但是关闭的窗口永远不会被释放,并且会在内存中不断堆积。
如果我移除windowController
赋值,当我尝试使用EXC_BAD_ACCESS
关闭窗口时,应用会崩溃,使用分析器,我可以看到窗口实际上已被解除分配:An Objective-C message was sent to a deallocated 'NSWindow' object (zombie) at address...
因此,我认为windowController
示例是罪魁祸首,并且永远不会被销毁。
如何为以编程方式创建的窗口实现正确的NSWindow生命周期?
1条答案
按热度按时间esyap4oy1#
由于历史原因,
NSWindow
的解除分配有点复杂,从NSWindow.close()
的文档中可以看到:如果窗口设置为关闭时释放,则在当前事件完成后会向对象发送释放消息。对于NSWindow对象,默认设置为关闭时释放,而对于NSPanel对象,默认设置为不释放。可以使用isReleasedWhenClosed属性更改默认行为。
来自
isReleasedWhenClosed
的文档:如果窗口在关闭后自动释放,则此属性的值为true;如果只是将其从屏幕中删除,则返回false。
NSWindow的默认值为true;NSPanel的默认值是false。2然而,对于窗口控制器拥有的窗口,关闭时释放被忽略。3释放NSWindow对象的另一个策略是让它的委托在接收到windowShouldClose(_:)消息时自动释放它。
如果您拥有该窗口,则
isReleasedWhenClosed
应为false
,并且可以删除窗口控制器。