mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-14 04:13:43 +00:00
fix(macos): release closed child window engines (#1639)
This commit is contained in:
3 files changed
+120
-1
No files matched your search
@@ -4,6 +4,8 @@ import desktop_multi_window
|
||||
import window_manager
|
||||
|
||||
class MainFlutterWindow: NSWindow {
|
||||
private var childWindowCloseObservers: [ObjectIdentifier: NSObjectProtocol] = [:]
|
||||
|
||||
override func awakeFromNib() {
|
||||
let flutterViewController = FlutterViewController()
|
||||
let windowFrame = self.frame
|
||||
@@ -11,13 +13,45 @@ class MainFlutterWindow: NSWindow {
|
||||
self.setFrame(windowFrame, display: true)
|
||||
|
||||
RegisterGeneratedPlugins(registry: flutterViewController)
|
||||
FlutterMultiWindowPlugin.setOnWindowCreatedCallback { controller in
|
||||
FlutterMultiWindowPlugin.setOnWindowCreatedCallback { [weak self] controller in
|
||||
RegisterGeneratedPlugins(registry: controller)
|
||||
self?.releaseChildEngineOnClose(controller)
|
||||
}
|
||||
|
||||
super.awakeFromNib()
|
||||
}
|
||||
|
||||
// desktop_multi_window removes closed windows from its registry, but plugin
|
||||
// channels can still retain the window/controller/engine cycle. NSWindow.close
|
||||
// alone therefore leaves each child Dart isolate and its heap running.
|
||||
private func releaseChildEngineOnClose(_ controller: FlutterViewController) {
|
||||
guard let window = controller.view.window else { return }
|
||||
let key = ObjectIdentifier(window)
|
||||
childWindowCloseObservers[key] = NotificationCenter.default.addObserver(
|
||||
forName: NSWindow.willCloseNotification, object: window, queue: .main
|
||||
) { [weak self, weak controller, weak window] _ in
|
||||
if let observer = self?.childWindowCloseObservers.removeValue(forKey: key) {
|
||||
NotificationCenter.default.removeObserver(observer)
|
||||
}
|
||||
// Let close notifications and the plugin's registry removal finish before
|
||||
// tearing down the engine that delivered the close request.
|
||||
DispatchQueue.main.async { [weak controller, weak window] in
|
||||
// window_manager's onEvent closure retains its plugin, which retains
|
||||
// the manager and NSWindow even after the engine has stopped.
|
||||
(window?.delegate as? WindowManager)?.onEvent = nil
|
||||
window?.delegate = nil
|
||||
controller?.engine.shutDownEngine()
|
||||
window?.contentViewController = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
for observer in childWindowCloseObservers.values {
|
||||
NotificationCenter.default.removeObserver(observer)
|
||||
}
|
||||
}
|
||||
|
||||
override public func order(_ place: NSWindow.OrderingMode, relativeTo otherWin: Int) {
|
||||
super.order(place, relativeTo: otherWin)
|
||||
hiddenWindowAtLaunch()
|
||||
|
||||
Reference in new issue
Block a user