I want to be able to retrieve the NSWindowController of a specific class of window opened by my app, returning the customer class of that window. The code walks through the window list, looking for the target view controller by calling -[NSObject isKindOfClass:], then returns the window controller when the target view is found. However, when I attempt to get the window's controller, windowController returns nil.
- (MyWindowController *) retrieveMyController {
MyWindowController *mwc;
NSArray *windows = [[NSApplication sharedApplication] windows];
NSWindow *window;
NSViewController *view;
NSInteger count = [windows count];
mwc = nil;
while (count--) {
window = [windows objectAtIndex:count];
view = window.contentViewController;
if ([view isKindOfClass:[MyViewController class]]) {
mwc = [window windowController];
return (mwc);
}
}
return (mwc);
}
The window is created in a storyboard and appears to be hooked up correctly: MyWindowController -> NSWindow -> MyViewController
Is there something I might be missing in retrieving my window controller from an NSWindow?
UPDATE:
Here's a little more information from the section of the storyboard that describes the window controller.
This first bit of code is for the window that returns nil when I attempt to get the window controller:
<!--Window Controller-->
<scene sceneID="d6J-4M-8Ta">
<objects>
<windowController storyboardIdentifier="Game Board" showSeguePresentationStyle="single" id="rtu-Zd-mSC" customClass="MyWindowController" sceneMemberID="viewController">
<window key="window" title="Game Board" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" tabbingMode="disallowed" id="Om0-DT-JQm">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="512" y="303" width="1440" height="860"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<value key="minSize" type="size" width="1440" height="860"/>
<connections>
<outlet property="delegate" destination="rtu-Zd-mSC" id="hWs-pg-5hH"/>
</connections>
</window>
<connections>
<segue destination="dCc-Ee-tuh" kind="relationship" relationship="window.shadowedContentViewController" id="Zh5-ae-o9K"/>
</connections>
</windowController>
<customObject id="QgT-xE-oJb" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-1549" y="1308"/>
</scene>
And this snippet of code is for another window in my app, but I am able to retrieve the window controller for this window:
<!--Window Controller-->
<scene sceneID="q0J-D1-Y9O">
<objects>
<windowController id="R9S-Kd-BY0" customClass="ProjectsWindowController" sceneMemberID="viewController">
<window key="window" title="Projects" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="0gH-R3-7qL">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="933" y="448" width="650" height="522"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
<value key="minSize" type="size" width="650" height="200"/>
<value key="minFullScreenContentSize" type="size" width="480" height="200"/>
<view key="contentView" id="JTv-nd-FxB">
<rect key="frame" x="0.0" y="0.0" width="650" height="522"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<connections>
<outlet property="delegate" destination="R9S-Kd-BY0" id="8fY-z4-N1F"/>
</connections>
</window>
<connections>
<segue destination="zDF-uA-d0p" kind="relationship" relationship="window.shadowedContentViewController" id="vxS-GV-TX6"/>
</connections>
</windowController>
<customObject id="U0q-V5-uQM" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-3884" y="-2830"/>
</scene>
The difference that immediately stands out is that the first window controller lacks a tag, which baffles me a little because the window certainly shows content, and when I walk through the code in the debugger [view isKindOfClass...] does return true.
(Editing this on a laptop right now that does not have Xcode installed, so I'll dig deeper once I'm home)
Okay, I figured this out. The reason why some of my windows would correctly return the window controller, while others return nil is due to how the windows are being created. Where my code looked like this...
...Subsequent attempts to retrieve the window controller from the NSWindow in the window list would return nil. This is entirely due to the fact that the controller is being instantiated into a local NSWindowController. By instead instantiating into a property, everything works as expected and a legitimate window controller is returned by subsequent calls to [window windowController].
Even though we all know that the life of a local variable is limited to only the method in which the variable is declared, the behavior strikes me as a little weird. The window and all of its content IS created and continues to function long after the method that created the window has run. The NSWindow is still around, the content view is still around, and the window and all its controls (seems to) function flawlessly. The only thing that's missing is the linkage back to the window controller. I.m sure there's a good reason, but... weird.