From 35f001b1fdee7e6c4f4927a1b70f7197ade00162 Mon Sep 17 00:00:00 2001 From: Mx-Iris Date: Wed, 12 Aug 2026 23:36:27 +0800 Subject: [PATCH] fix(attach): give every document its own attach-to-process sheet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The controller was a shared singleton behind `@Dependency(\.attachToProcessViewController)`, so all open documents presented the same instance. Attach To Process is presented as a sheet on the document's root window, and a view controller can only be presented from one window at a time — opening it in a second document while the first still has it up crashes the app. `setupBindings(for:)` also rebinds the shared instance to the second document's view model, so the first document's sheet would keep driving the wrong document even without the crash. Construct the controller per presentation instead, the way every other route in MainCoordinator does. This gives up what 6849d78 bought: the picker no longer remembers the last-selected tab and row across reopens. That state belongs in the view model or AppDefaults, not in a controller instance shared between documents. --- .../Attach Process/AttachToProcessViewController.swift | 9 --------- .../RuntimeViewerUsingAppKit/Main/MainCoordinator.swift | 3 +-- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/RuntimeViewerUsingAppKit/RuntimeViewerUsingAppKit/Attach Process/AttachToProcessViewController.swift b/RuntimeViewerUsingAppKit/RuntimeViewerUsingAppKit/Attach Process/AttachToProcessViewController.swift index 5352542a..5f7ba498 100644 --- a/RuntimeViewerUsingAppKit/RuntimeViewerUsingAppKit/Attach Process/AttachToProcessViewController.swift +++ b/RuntimeViewerUsingAppKit/RuntimeViewerUsingAppKit/Attach Process/AttachToProcessViewController.swift @@ -8,8 +8,6 @@ import DependenciesMacros final class AttachToProcessViewController: UXKitViewController { override var shouldDisplayCommonLoading: Bool { true } - - fileprivate static let shared = AttachToProcessViewController() private let pickerViewController: RunningPickerTabViewController @@ -73,10 +71,3 @@ extension AttachToProcessViewController: RunningPickerTabViewController.Delegate cancelRelay.accept() } } - -// MARK: - Dependencies - -extension DependencyValues { - @DependencyEntry(liveValue: MainActor.assumeIsolated { AttachToProcessViewController.shared }) - var attachToProcessViewController: AttachToProcessViewController -} diff --git a/RuntimeViewerUsingAppKit/RuntimeViewerUsingAppKit/Main/MainCoordinator.swift b/RuntimeViewerUsingAppKit/RuntimeViewerUsingAppKit/Main/MainCoordinator.swift index d6778000..a7ce7f23 100644 --- a/RuntimeViewerUsingAppKit/RuntimeViewerUsingAppKit/Main/MainCoordinator.swift +++ b/RuntimeViewerUsingAppKit/RuntimeViewerUsingAppKit/Main/MainCoordinator.swift @@ -9,7 +9,6 @@ import LateResponders typealias MainTransition = SceneTransition final class MainCoordinator: SceneCoordinator, LateResponderRegistering { - @Dependency(\.attachToProcessViewController) private var attachToProcessViewController let documentState: DocumentState @@ -86,7 +85,7 @@ final class MainCoordinator: SceneCoordinator, LateRe viewController.setupBindings(for: viewModel) return .uxPopover(viewController, relativeTo: sender.bounds, of: sender, preferredEdge: .maxY, behavior: .transient, animates: true) case .attachToProcess: - let viewController = attachToProcessViewController + let viewController = AttachToProcessViewController() let viewModel = AttachToProcessViewModel(documentState: documentState, router: self) viewController.setupBindings(for: viewModel) viewController.preferredContentSize = .init(width: 800, height: 600)