Cocoa Window Not Showing on macOS Sierra

I have the following code to show a new window in my macOS app.


let mainStoryBoard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil)
let windowController = mainStoryBoard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "WindowController")) as! NSWindowController
let myController = windowController.window!.contentViewController as! ViewController
myController.imageView.image = mainImage
windowController.showWindow(self)


`mainImage` is defined above that.


Problem is this code works perfectly on macOS High Sierra, but on macOS Sierra the window sometimes displays for a split second then disappears.


Why would this work on macOS High Sierra but not macOS Sierra?

I did notice some behavior changes in window management from 10.12 to 10.13. Just as if some sequences of api calls were modified.


Where do you have the code :

let mainStoryBoard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil)

let windowController = mainStoryBoard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "WindowController")) as! NSWindowController

let myController = windowController.window!.contentViewController as! ViewController

myController.imageView.image = mainImage

windowController.showWindow(self)


I would try to repeat the call to showWindow(nil) later in code

So like the following?


let mainStoryBoard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil)
let windowController = mainStoryBoard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "WindowController")) as! NSWindowController
let myController = windowController.window!.contentViewController as! ViewController
myController.imageView.image = mainImage
windowController.showWindow(self)
windowController.showWindow(nil)


If that is incorrect I'm not sure what you mean by later in code.


And just tested this, same problem.

Claude was asking where this code is (in what method of what class), and it would be interesting to know the answer. Also, this is an additional window, right? The first one should appear automatically without this code, unless you've taken steps to prevent that.


However, on the face of it, your code looks just plain wrong. You're assigning the window controller to a local variable, whose lifetime is the enclosing scope. As soon as you exit that scope, the reference is discarded, and there's nothing keeping the window controller alive. At that point, the window controller can deallocate, and cause the window to deallocate too.


If it worked in the past, that's likely because the window (or a subordinate view controller or view) caused a retain cycle that kept the window alive. If that happened before the scope was exited, the window would stay around. Since different macOS versions may have different timing, the window might disappear before the retain cycle was created, in some cases. (Alternatively, this might have something to do with the window's "release when closed" attribute, or another cause, but the lack of a retaining reference is the most likely cause.)


Anyway, the solution is to keep a persistent reference to the window controller somewhere, and to manually discard the reference when the window closes.

So I have a NSOpenPanel that on completion will display a new window. This all takes place within the applicationDidFinishLoading. There is no default window. I have unchecked the inital controller for the window controller in interface builder.


Any tips for how I could keep a persistent reference? Would just moving the scope of one of those variables into a higher scope and then setting the reference equal to those things work maybe?

In default of any better choice, make a property in your app delegate. If there can only be one of these windows, it can be a simple NSWindowController property. Otherwise, keep an array of them. You can set/add the reference when you create the window controller, and nil/remove it in (say) the window controller's "windowWillClose" method.

Hi charliefish,


You need to strongly reference the NSWindow/Controller somewhere for the lifetime of the window. macOS 10.13 introduced a behavior where NSWindow will retain itself for as long as it is "open", but previous versions of the OS didn't have this behavior. As a result, if you aren't retaining the window, it'll be deallocated and removed from the screen.

Cocoa Window Not Showing on macOS Sierra
 
 
Q