Window not Visible At Launch

I want a window to not appear at launch to be able to control later how and where. In storyboard I select Window / Attributes and deselect "Visible At Launch" but it still appears. I even tried a new project with no code and just one window and it happens the same. Am I missing anything? Why is it not working? How to hide the window at the beginning?

Replies

I tested in a project and the window doesnot show if 'Visible At Launch' is turned off.


Where is the window ? In the MainMenu.xib ?

Or are you using a document based app ?


Try an option clean Build Folder, in case.


Which version of XCode ?

Which version of MacOS ?

I do New Project > macOS > App > User Interface Storyboard

I go to Main.storyboard > Attributes > Select Window (Inside Window Controller) and check that Visible At Launch is not selected by default

I click the play button and a window appears


I have "clean build folder" and try again. It appears.


MacOS 10.14.6

Xcode 11.1


You have defined with Storyboard.


And your windowController is declared as initial controller.

That's why it is forced visible.


If you create a new project, and select xib instead of storyboard, you will get only a main menu and a window (may be anywhere in the canvas, take care to find it).

Now, you can make it invisible at launch.


You can stay with storyboard, remove the initial controller arrow, window will not be visible.

But you cannot then ask to make it visible at launch.


Conclusion, in storyboard, initialController and visible at launch are linked together (don(t know where it's documented).

Thank you very much!. I had no idea. I was completely lost. I understand your explanation on how to make it not visible at launch. But I still do not understand how it works as a whole. How to make it appear later?. I have been searching for tutorials, or anywhere that could explain the whole picture and I cannot find it.


What I try to do is to control the position and size of the window from the beginning. I tried that on the viewDidLoad. I give some seconds to load the page. (without that I could not see the page)

DispatchQueue.main.asyncAfter(deadline: .now() + 3.0){

self.view.window?.setFrame(NSRect(x:10,y:10,width:200,height:100), display: true)

}


This works in regular storyboard but the window appears and then reposition. A strange effect. That is why I wanted to hide on the beginning. If I use xip, I have no place to put the code to open the window later. If I use the storyboard and delete the arrow, that code does not work, gives me an error. Sorry, I do not know where to go to learn. Thank you in any case.

What scheme have you selected ? xib or Storyboard ?


With a storyboard, here is a solution.


Define a class for the window.


Outside of class definition create a var for the controller


import Cocoa

var firstController : NSWindowController?

class FirstWindowController: NSWindowController, NSWindowDelegate {

    override func windowDidLoad() {
        super.windowDidLoad()
       
        firstController = self
    }

}



The windowController is set to class FirstWindowController.


In IB, insert a MenuItem, 'Show', for instance aa first item of File menu.

Control drag from this item to AppDelegate, to create an IBAction


import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {


    @IBAction func showWindow(_ sender: NSMenuItem) {
        firstController?.showWindow(self)
    }
   
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }

}


If the window is hidden or if you closed it, call this 'Show' menuItem to make it appear.

I had to struggle some time to get the initial view appear at the right position and size.


Here it is for a xib (MainMenu.xib), in which a window (splashWindow) is defined and connected to its IBOutlet in AppDelegate.

I set the frame in appDidFinishLaunching


class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {

    @IBOutlet weak fileprivate var splashWindow : NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) {

        let screen: NSScreen = NSScreen.main!
        let midScreenX = screen.frame.midX
        let posScreenY = 200
        let origin = CGPoint(x: midScreenX - 300, y: posScreenY) // 300: half width
        let size = CGSize(width: 600, height: 200)
        frame = NSRect(origin: origin, size: size)
        splashWindow.setFrame(frame, display: true)
     }

}

For a Storyboard app, I did it this way (works also for xib based).


1. Create a subclass of NSWindow


2. Set the initial windowController to this class


3. Change the frame in windowDidBecomeMain


import Cocoa

class FirstWindowController: NSWindowController, NSWindowDelegate {

    override func windowDidLoad() {
        super.windowDidLoad()
   
        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
    }
   
    func windowDidBecomeMain(_ notification: Notification) {
        let newFrame = NSRect(x: 120, y: 100, width: 300, height: 200)
        print(#function, self.window?.frame)
        self.window?.setFrame(newFrame, display: true)
        print(#function, self.window?.frame)
    }
   
}

Note: Make sure to quit the app before running with new frame value.


If you do so, you may have to manage a new property for the window

var firstAppearance = true


otherwise, when you move the window, select another one and reselect it, it will return to this position.


So, code becomes:


class FirstWindowController: NSWindowController, NSWindowDelegate {

    fileprivate var firstAppearance = true

    override func windowDidLoad() {
        super.windowDidLoad()

        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
    }

    func windowDidBecomeMain(_ notification: Notification) {
        if firstAppearance {
            let newFrame = NSRect(x: 120, y: 100, width: 300, height: 200)
            self.window?.setFrame(newFrame, display: true)
        }
     firstAppearance = false
    }

Thank you for your answers. I cannot make it work. I need to find tutorials to learn the basics. It is not easy to find material to learn macOS.

If you want, post me for a momemnt an email address, so that we can share files. I will tell you, on your project, how to implement.