我正在用 SwiftUI 编写一个多平台应用程序。
它可以处理 3 种不同类型的窗口,以及用户想要打开的任意数量的窗口实例。
当用户关闭窗口时,我需要进行一些清理,因此我将以下内容添加到视图层次结构中的顶级视图中(在本例中为
NavigationStack
)
.onReceive(NotificationCenter.default.publisher(for: NSWindow.willCloseNotification)) { newValue in
// Do cleanup
}
我的期望是,当包含此特定 View 对象的特定窗口关闭时,将调用我的
.onReceive
处理程序的闭包。
如果你在AppKit中查找
NSWindow.willCloseNotification
,它表示它将通知发送到即将关闭的特定窗口对象。
但是,似乎在 SwiftUI 中,当任何窗口即将关闭时,它都会在每个窗口上调用。
为什么会这样?当 NSWindow 的特定实例即将关闭时,是否有一些技巧可以获取通知?
如果你在AppKit中查找
,它表示它将通知发送到即将关闭的特定窗口对象。NSWindow.willCloseNotification
我认为这里可能对文档试图表达的内容存在误解。来自文档:
通知对象是即将关闭的
对象。此通知不包含NSWindow
字典。userInfo
Notification.object
,它是一个通用属性(一般,不是<T>
意义上的),描述与通知相关的对象。有些通知是全局的,与特定对象无关(在这种情况下,它可以是 nil
),而其他通知则指示与特定对象相关的更改,在这种情况下,这将被设置。
在这种特定情况下,为
object
收到的 Notification
的 NSWindow.willCloseNotification
属性被记录为将要关闭的窗口,以便您可以区分可以关闭的窗口。
不过,Notification.object
不仅仅是接收通知时的相关信息:您可以使用特定对象作为订阅通知时接收通知的 filter。 NotificationCenter.addObserver(forName:object:queue:using:)
和 NotificationCenter.addObserver(_:selector:name:object:)
都允许您传递 object
参数,以便仅传递 .object
与给定对象匹配的通知 - 即,如果您只关心接收 NSWindow.willCloseNotification
一个特定窗口对象,您可以预先传递它,只有当.object
匹配时才会发送通知。
NotificationCenter.publisher(for:object:)
also 允许您传入 object
进行过滤——它恰好默认为 nil
(这意味着不应用过滤器)。订阅没有对象的通知的最终效果是,每个订阅的窗口都将收到关闭的any窗口的通知;即,正是您所看到的。
如果您希望每个视图层次结构仅在其包含窗口即将关闭时得到通知,则需要提供对包含
NSWindow
到publisher(for:object:)
的引用。 (我不认为有直接的方法可以访问 SwiftUI 中包含的 NSWindow
,因此您可能需要在创建顶级视图时传递引用。)