I have just encountered this exact same issue, and indeed, keeping a copy around of my window solved the issue. The approach that I took was a little different though and did not require me to create a property in the caller, but rather I managed to find a way to do it all locally.
So, my panel NSWindowController has a method which allows it to be presented in another NSWindow as a panel, here's what the method signature looks like (in Swift):
@objc func presentInWindow(_ window: NSWindow, callback: @escaping FileFormatSelectionResult)Where FileFormatSelectionResult is a closure defined as:
typealias FileFormatSelectionResult = (SelectedFormat, Bool) -> VoidThe closure is stored inside my NSWindowController instance until such time as the user makes a selection (Cancel or Import) which dismisses the sheet. After the sheet is dismissed, the callback closure is called.
This allowed me to write the following code in the caller (in Objective-C) which keeps the sheet NSWindowController around for the duration of the interaction:
The __block variable for the panel NSWindowController instance allows the block to capture it, and set it to nil at the end of the interaction, without the need to introduce a property or a local variable in the caller. The same could be accomplished in Swift as well.
I thought I'd post this here in case someone else runs into this issue and needs a simple approach to solving it.
Hope it helps.