Programmatic equivalent of "Visible at Launch" for NSWindows - cocoa

I'm trying to write the programmatic equivalent of a nib file I've setup that contains two windows: a main window and sheet that appears after launch to prompt for credentials. Wiring these up in IB works fine, so long as one remembers to uncheck the "Visible at Launch" box on the sheet/window.
However I can't figure out what the API equivalent is of "Visible at launch". When I run my app using the programmatic version the sheet is detached and not the key view in the same way my app ran with the nib when "Visible at Launch" was checked. So my assumption, then, is that I'm missing the secret visible-at-launch sauce.
Does anyone know how to do this?
P.S. I know how to make this work in IB, I specifically want to figure out the code equivalent so please don't tell me to just use the nib. I know that.

NSWindows are typically created hidden. So you shouldn't have to do anything; just don't show the window until you need it. Here's a simple example.
NSWindow *sheetWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100) styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:NO];
NSTextField *field = [[NSTextField alloc] initWithFrame: NSMakeRect(25, 25, 50, 50)];
[[sheetWindow contentView] addSubview:field];
[NSApp beginSheet:sheetWindow modalForWindow:[self window] modalDelegate:self didEndSelector:#selector(sheetDidEnd:) contextInfo:NULL];
The text field obtained keyboard focus when I ran the above.
In future, please provide code in cases like this—it's a lot easier to correct existing code than to write new code.

Related

Creating an NSWindow that floats over all other windows in the app but not over windows from other apps

I am trying to make my NSWindow always show up on top in my application but I don't want it to float over other apps that have become active. I have tired the following code but this makes the window float over other applications:
NSRect frame = NSMakeRect(100, 100, 800, 800);
myWindow = [[NSWindow alloc] initWithContentRect:frame
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[myWindow setLevel:NSFloatingWindowLevel ];
[myWindow setBackgroundColor:[NSColor blueColor]];
[myWindow makeKeyAndOrderFront:NSApp];
I have also tried all of the constants listed in the NSWindow documentation and did not find one that would make the NSWindow float over other windows in my but not other windows of other active apps. Is this not possible?
There's no built-in support for that. You might consider setting your window to hide on deactivate.
Alternatively, you can have the window controller observe the NSApplicationWillResignActiveNotification and NSApplicationDidBecomeActiveNotification notifications and adjust the window level. When your app is about to resign active status, you set the window level back to normal. When it becomes active again, you set it to float. (If the window is controlled by the app delegate, then you can do this in the -applicationWillResignActive: and -applicationDidBecomeActive: delegate methods.)

recalculateKeyViewLoop doesn't work

In my cocoa application I want to change the key order of my views. I fill in the nextKeyView reference for all subviews in the desired order. In the view's awakeFromNib function I do the following:
[[self.view window] setInitialFirstResponder:self.view];
[[self.view window] setAutorecalculatesKeyViewLoop:NO];
[[[self view] window] recalculateKeyViewLoop];
where the nextKeyView for the self.view is set to the first subview I want to appear in key order.
Nothing helps and the the key ordering stays default. How to resolve it?
Thanks
Calling recalculateKeyViewLoop forces the window to automatically calculate the key-view loop. You don't want to do this if you've set the key-view loop manually, as it does exactly what you've just told the window not to do in [[self.view window] setAutorecalculatesKeyViewLoop:NO].
You don't need any of this code. In Interface Builder, make sure your window has the "Auto Recalculates View Loop" checkbox un-checked, and connect the initialFirstResponder outlet of your window to the view that you want to be the initial first responder.
No code required.
following on from Rob's answer, in XCode 7.3 you can find the checkbox in the Interface Builder for the main window under:

Set focus on a NSTextField in an NSMenu?

I have an NSMenu in the Mac statusbar, inside it I have a load of NSMenuItems and a custom view. Inside the custom view I have an NSTextField. I want to set the focus on the NSTextField when the menu is opened as in the Spotlight menu so the user can type straight away.
I have tried quite a few methods including:
[myTextField becomeFirstResponder];
and
[myTextField selectText: self];
[[myTextField currentEditor] setSelectedRange:NSMakeRange([[myTextField stringValue] length], 0)];
but none of them work.
Thanks
Alex
You were on the right track with the first one, but -becomeFirstResponder doesn't actually make your view the first responder--you have to call -[NSWindow makeFirstResponder:] for that.
Google suggests that NSMenus actually have an attached window. You have to use it very carefully, but it is safe to call makeFirstResponder: on it.
More information about this and how to take advantage of it here: https://web.archive.org/web/20171113100008/http://www.cocoabuilder.com/archive/cocoa/195835-set-focus-on-nsview-in-an-nsmenuitem.html

Creating a checkbox programmatically using Cocoa

I need to create a checkbox programmatically in Cocoa and when I try and make a button with buttonType set to NSSwitchButton it displays the title, but does not show the button as a checkbox. I think I am missing something but I can't find any resources about making things like checkboxes without using the Xcode GUI.
The question is a little old so you've probably already figured it out, but I found it while searching for this exact thing. Alex danced around the solution without actually providing it. So here, for Google and all mankind: how to programmatically create a checkbox in Cocoa.
NSRect frame;
frame.size.width = frame.size.height = 18;
NSButton *myCheckBox = [[NSButton alloc] initWithFrame:frame];
[myCheckBox setButtonType:NSSwitchButton];
[myCheckBox setBezelStyle:0]; // This is unnecessary. I include it to show that checkboxes don't have a bezel style.
[myView addSubview:myCheckBox];
I don't think buttons are bezeled by default when created programmatically. Check the setBezelStyle: method, as well as setBezeled: and setBordered:. One of those should give you what you want.
I had failed to execute setImagePosition properly and this was causing the checkbox not to display.

Why the splash window can’t show before the App launch?

I want to show a splash Screen before the App lunch. First I make the SplashWindow subclassing the NSWindow, the code is :
- (id)initWithContentRect(NSRect)contentRect
styleMask(unsigned int)aStyle
backing(NSBackingStoreType)bufferingType
defer(BOOL)flag {
self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
[self setBackgroundColor:
[NSColor clearColor]];
[self setLevel: NSStatusWindowLevel];
[self setAlphaValue:1.0];
[self setOpaque:NO];
[self setHasShadow: YES];
return self;
}
and then in the awake from nib in the main app controller:
loadWindow = [[NSWindow alloc] initWithContentRect:[loadWindow frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
[loadWindow setContentView:theView];
[loadWindow setHasShadow:YES]; [
loadWindow setLevel:NSStatusWindowLevel];
[loadWindow makeKeyAndOrderFront:self];
and then I let the loadWindow closed after 3 secondes, I used the method [loadWindow orderOut:self], but when the splash window closed , the mainwinow didn't show . what am I missing? My App is a multi_Documents . and in the mainMenu.nib there was one window(loadwindow),in IB I have connected up the loadWindow outlet in the main controller. I have also connected the view and image. and I changed another way : in the delegate method:applicationWillFinishLaunching: I orderFront the loadWindow , in the method:applicationDidFinishLaunching: I orderOut the loadWindow after 3 seconds, but the mainWindow didn't show too.Somebody can give some advice or codes the result the problem? Thank you very much!
Answer to title: Because your app isn't running yet. An application that isn't running can't do anything.
Serious answer to question:
First, you don't need to subclass NSWindow.
Second, you aren't instantiating your subclass, you're instantiating NSWindow. That's why you're not getting your subclass's behavior. (And this is what you should be doing, since you don't need the subclass.)
Third, you're trying to ask a window that doesn't exist yet for the frame you'll use to create it. loadWindow is nil until after you create something and store it there.
Fourth, because you are asking nil for its frame, you are getting a garbage rectangle back. Then you create a window with this garbage rectangle. Unsurprisingly, when you put this window on the screen, it appears in a random position (probably off-screen) with a random size (probably either too large to create or negative).
Fifth, what makes you think that telling a window to order out would cause some other window to order in? How is it supposed to know what window to order in?
Leaving aside the undeniable reality that the very existence of a splash screen punishes the user for using your application, you should be using NSWindowController to load the window and to do your set-up such as setBackgroundColor: and setLevel:. And in your timer method, where you order out the splash window, you must also explicitly order in the main window.
I don't see anything that would make another window show in the code you posted. Why don't you try sending your main window makeKeyAndOrderFront:?

Resources