You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关闭窗口后WKWebView仍持续播放音频问题求助

问题分析与解决方案

这不是操作错误,是你给主窗口设置自定义NSWindowDelegate后,改变了SwiftUI默认的窗口生命周期行为导致的问题。

问题原因

默认情况下,SwiftUI的WindowGroup管理的窗口,在点击关闭按钮时会销毁对应的视图层级(包括内嵌的WKWebView),且应用进程会在最后一个窗口关闭后自动终止。但当你给窗口绑定了自定义NSWindowDelegate,系统会判定你要手动接管窗口生命周期,此时点击关闭按钮仅会隐藏窗口,不会销毁WebView实例,进程也不会终止,所以音频会在后台持续播放。

修复方案

你可以通过以下两种方式解决:

方案1:恢复窗口默认关闭&进程终止行为

在AppDelegate中实现windowShouldClose方法,并设置应用在最后一个窗口关闭时自动终止:

class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject, NSWindowDelegate {
    func applicationDidFinishLaunching(_ notification: Notification) {
        if let mainWindow = NSApp.keyWindow {
            mainWindow.delegate = self
        }
        // 让应用在最后一个窗口关闭后自动终止
        NSApp.terminateAfterLastWindowClosed = true
    }
    
    // 明确允许窗口关闭
    func windowShouldClose(_ sender: NSWindow) -> Bool {
        return true
    }
}

方案2:窗口关闭时手动停止WebView播放

如果需要保留窗口实例(比如支持快速恢复),可以在窗口关闭时主动停止WebView的加载并清空内容:
首先给PlayerWebView添加停止播放的方法:

struct PlayerWebView: NSViewRepresentable {
    private let webView = WKWebView(frame: .zero)
    
    func makeNSView(context: Context) -> WKWebView {
        let url = URL(string: "https://www.youtube.com/embed/Ir1xi2zeuug")!
        let request = URLRequest(url: url)
        webView.load(request)
        return webView
    }

    func updateNSView(_ nsView: WKWebView, context: Context) {}
    
    // 添加停止播放的方法
    func stopPlaying() {
        webView.stopLoading()
        webView.loadHTMLString("", baseURL: nil)
    }
}

然后在AppDelegate的窗口关闭回调中调用该方法(需确保能获取到PlayerWebView的实例,可通过环境对象、全局引用等方式实现):

class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject, NSWindowDelegate {
    @EnvironmentObject private var playerWebView: PlayerWebView
    
    func applicationDidFinishLaunching(_ notification: Notification) {
        if let mainWindow = NSApp.keyWindow {
            mainWindow.delegate = self
        }
    }
    
    func windowWillClose(_ notification: Notification) {
        playerWebView.stopPlaying()
    }
}

额外提示

如果你的需求只是监听窗口事件,不一定需要自定义NSWindowDelegate——SwiftUI的WindowGroup可以通过.onChange(of: NSApp.windows)或者结合NSWindow的发布者来实现监听,这样能避免修改默认的窗口生命周期行为。

内容的提问来源于stack exchange,提问作者fer0n

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:05:55