SwiftUI 和 macOS:如何检测关闭的最后一个窗口并显示应用程序将退出的警报
Posted
技术标签:
【中文标题】SwiftUI 和 macOS:如何检测关闭的最后一个窗口并显示应用程序将退出的警报【英文标题】:SwiftUI & macOS : How to detect last window being closed and show alert that app will quit 【发布时间】:2021-08-25 17:56:47 【问题描述】:我正在创建一个 SwiftUI 应用程序。在用户关闭最后一个窗口时,我想提示用户并通知他们应用程序也将退出。
我查看了在应用程序退出时创建警报的两种解决方案here,还查看了在最后一个窗口关闭时关闭应用程序的解决方案here。
然而,我已经开始工作了,但没有一起工作。我正在寻找一种方法来检测用户何时关闭应用程序中的最后一个窗口,然后通过警报提示用户,让他们知道它将退出应用程序并询问他们是要继续还是取消。
使用.onDisappear
似乎不起作用。我已经实现了一个appDelegate
,它是applicationShouldTerminateAfterLastWindowClosed
方法,但是当最后一个窗口关闭时,它似乎没有在我的应用程序中提示.alert
行为。
Application
类
class Application: NSObject, NSApplicationDelegate, ObservableObject
@Published var willTerminate = false
override init()
super.init()
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply
if NSApplication.shared.windows.count == 0
return .terminateNow
self.willTerminate = true
return .terminateLater
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool
return true
func resume()
NSApplication.shared.reply(toApplicationShouldTerminate: false)
func close()
NSApplication.shared.reply(toApplicationShouldTerminate: true)
struct WindowAccessor: NSViewRepresentable
@Binding var window: NSWindow?
func makeNSView(context: Context) -> NSView
let view = NSView()
DispatchQueue.main.async
self.window = view.window
return view
func updateNSView(_ nsView: NSView, context: Context)
ContentView
struct ContentView: View
@State private var window: NSWindow?
@EnvironmentObject private var appDelegate: Application
var body: some View
ZStack
MyView()
// ...
.onDisappear(
// Code in here does not run when WindowAccessor is set to background
)
.background(WindowAccessor(window: self.$window))
.alert(isPresented: Binding<Bool>(get: self.appDelegate.willTerminate && self.window?.isKeyWindow ?? false , set: self.appDelegate.willTerminate = $0 ), content:
SoloLogger(for: .window).coreLog(message: "ApplicationClosedEvent", level: .info)
return Alert(title: Text("Quit Application?"),
message: Text("Do you really want to quit the application?"),
primaryButton: .default(Text("Cancel"), action: self.appDelegate.resume() ),
secondaryButton: .destructive(Text("Quit"), action: self.appDelegate.close()))
)
【问题讨论】:
你找错人了。在developer.apple.com/documentation/appkit/… 选择合适的。 我用错了“人”?你可以再详细一点吗?如上代码所示,我实现了应用委托。 赞成。我也有同样的问题。 【参考方案1】:我一直在做类似的事情。
您可以从环境中获取@AppDelegate,无需创建WindowAccessor。
我创建了一个可以添加到内容视图的 ZStack 中的视图:
struct MacOSQuitCheckView: View
// MARK: - PROPERTIES
@EnvironmentObject private var appDelegate: AppDelegate
// MARK: - VIEW BODY
var body: some View
EmptyView()
.alert("App wants to quit?"), isPresented: isPresented)
Button("Do not quit", role: .cancel, action: appDelegate.resume)
Button("Quit", action: appDelegate.close)
// MARK: - PRIVATE COMPUTED PROPERTIES
private var isPresented: Binding<Bool>
Binding<Bool>(get: self.appDelegate.willTerminate , set: self.appDelegate.willTerminate = $0 )
【讨论】:
以上是关于SwiftUI 和 macOS:如何检测关闭的最后一个窗口并显示应用程序将退出的警报的主要内容,如果未能解决你的问题,请参考以下文章
(SwiftUI, MacOS 11.0) 如何在 SecureTextFeild 中检测焦点?
如何检测何时点击 TextField? (MacOS 上的 SwiftUI)
如何在 SwiftUI 生命周期中删除 macOS 中的最大化、最小化和关闭按钮?