self.window.isVisible = NO not working in windowDidLoad

The following code won't work:

- (void)windowDidLoad {
    [super windowDidLoad];

    self.window.isVisible = NO;
}

The only main window still shows on application startup (in a minimal newly created app).

One of my published apps in App Store relies on this behavior which had been working for many years since I started Xcode development.

Answered by DTS Engineer in 831036022

Looking at the documentation it's not clear to me if it is safe to try to hide a window inside of the NSWindowController's windowDidLoad method. Also, isVisible is a defined as a read-only property:

@property (readonly, getter=isVisible) BOOL visible;

so if it ever was working that was probably a bug. To hide a window you need to call orderOut:. I did some testing here and it appears that calling orderOut: to hide a window inside of the NSWindowController's windowDidLoad method does not work. However, if you call orderOut: later on the main thread using performSelectorOnMainThread:withObject:waitUntilDone::

[self.window performSelectorOnMainThread:@selector(orderOut:)
							  withObject:self.window
						   waitUntilDone:NO];

The window will be hidden as expected.

It's not entirely clear to me if calling orderOut: inside of the NSWindowController's windowDidLoad method should work. windowDidLoad is called after the window has been loaded from the nib, but it's not clear from the documentation and header comments if you can modify any of the parameters at that time. If you're interested in finding out the definitive answer I suggest filing a bug report.

If you file a bug report, please include an Xcode project and some directions that can be used to reproduce the problem. And after that please post the Feedback number here. I'll check the status and provide an update (if there's anything to report) next time I do a sweep of forums posts where I've suggested bug reports.

Bug Reporting: How and Why? has tips on creating your bug report.

I had wrong method name in initial post.

- (void)awakeFromNib {
    //NSApp.activationPolicy = NSApplicationActivationPolicyProhibited;
    self.window.isVisible = NO;
}

It seems setting isVisible to "NO" does not work - the window still shows.

Looking at the documentation it's not clear to me if it is safe to try to hide a window inside of the NSWindowController's windowDidLoad method. Also, isVisible is a defined as a read-only property:

@property (readonly, getter=isVisible) BOOL visible;

so if it ever was working that was probably a bug. To hide a window you need to call orderOut:. I did some testing here and it appears that calling orderOut: to hide a window inside of the NSWindowController's windowDidLoad method does not work. However, if you call orderOut: later on the main thread using performSelectorOnMainThread:withObject:waitUntilDone::

[self.window performSelectorOnMainThread:@selector(orderOut:)
							  withObject:self.window
						   waitUntilDone:NO];

The window will be hidden as expected.

It's not entirely clear to me if calling orderOut: inside of the NSWindowController's windowDidLoad method should work. windowDidLoad is called after the window has been loaded from the nib, but it's not clear from the documentation and header comments if you can modify any of the parameters at that time. If you're interested in finding out the definitive answer I suggest filing a bug report.

If you file a bug report, please include an Xcode project and some directions that can be used to reproduce the problem. And after that please post the Feedback number here. I'll check the status and provide an update (if there's anything to report) next time I do a sweep of forums posts where I've suggested bug reports.

Bug Reporting: How and Why? has tips on creating your bug report.

I forgot to mention that my tests are done on the old XIB project because my app was created long ago before storyboard was invented.

I tested again on my old MBP with Xcode 14.2 and macOS 12.7.6 (Monterey).

Either combination works:

  • Leave "Visible at Launch" checked (default) in IB and self.window.isVisible = NO in awakeFromNib
  • Uncheck "Visible at Launch" in IB and self.window.isVisible = YES in awakeFromNib

I believe there are some minor changes at the lower OS level that break this "old" behavior.

Actually when it comes to the real world, things become even weird.

In the App Store app project, I unchecked "Visible at Launch" but when I debug/run the app, the main window still shows. It's even true after I comment out awakeFromNib in which I do lots of initialization work.

Mystical event happens when I debug the following code:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [NSOperationQueue.mainQueue addOperationWithBlock:^{
        [self.mainWC setup];
    }];
}

I add a watch self.window.visible and set 2 breakpoints: one at the addOperationWithBlock line and the other inside the block.

When the first breakpoint is hit, self.window.visible is NO. But as soon as the second breakpoint is hit, self.window.visible becomes YES.

In IB "Visible at Launch" is unchecked for the main window. I have tried clean and rebuild but to no avail.

But I cannot reproduce this in a newly created project with similar XIB setup.

Does anyone else have such a bizarre situation like mine?

self.window.isVisible = NO not working in windowDidLoad
 
 
Q