I have a NIB with two NSWindow objects. The controller class has two IBOutlets, one for each NSWindow (windowLogin and windowMain).
I only want one of the windows visible on launch. Insdide awakeFromNib I am using:
[windowMain orderOut:self];
which is having no effect. However, if I try:
[windowMain setTitle:#"Renamed Title"];
It works as expected.
Thoughts?
Look for the "Visible At Launch" property in the attributes inspector for the window in Interface Builder.
Alternatively, in ApplicationDidFinishLoading, you can call [window setIsVisible:NO]
Related
I would like to track each time a certain window appears (becomes visible to the user) in a OS X app. Where would be the most adequate place to call the tracker?
windowWillLoad, maybe?
I expected to find something like windowWillAppear but it seems I'm thinking too much iOS.
How about getting notification such as NSWindowDidBecomeMainNotification, By main I guess the one which is top most on screen directly visible by user.
see : Apple Documentation
Yes, one would expect that a window would notify its delegate or its controller with a windowWillAppear or windowDidAppear message, or post a documented notification like NSWindowDidAppearNotification. But alas, none of those exist. I filed a bug report with Apple and was given the advice to use a storyboard and a view controller instead. This is unhelpful in legacy apps that already use a bunch of window controllers and xibs.
You could subclass NSWindow and override orderWindow:relativeTo: to send a notification. Most, but not quite all, of the messages that make a window show itself ultimately go through this method, including orderBack:, orderFront:, makeKeyAndOrderFront:, and -[NSWindowController showWindow:]. But orderFrontRegardless does not go through orderWindow:relativeTo:, so you would also want to override that for completeness.
Another way to be notified is to make a subclass of NSViewController that controls some view that's always visible in the window. The view controller will receive viewWillAppear and viewDidAppear.
If you're subclassing NSWindow or NSViewController already for some other reason, either of these is a reasonable solution.
If you're not subclassing NSWindow already, and don't have an NSViewController subclass for a view that's always visible in the window, then another way is to use Cocoa bindings to connect the window's visible binding to a property one of your objects. For example, I have a custom NSWindowController subclass. I gave it a windowIsVisible property:
#interface MyWindowController ()
#property (nonatomic) BOOL windowIsVisible;
#end
and I implemented the accessors like this:
- (BOOL)windowIsVisible { return self.window.visible; }
- (void)setWindowIsVisible:(BOOL)windowIsVisible {
NSLog(#"window %# became %s", self.window, windowIsVisible ? "visible" : "hidden");
}
and in awakeFromNib, I bind the window's visible binding to the property like this:
- (void)awakeFromNib {
[super awakeFromNib];
[self.window bind:NSVisibleBinding toObject:self withKeyPath:NSStringFromSelector(#selector(windowIsVisible)) options:nil];
}
When the window becomes visible, the setWindowIsVisible: setter is called with an argument of YES. Note that if the whole app is hidden and reappears, the setter is called again, even though it wasn't called with argument NO when the app was hidden. So be careful not to assume the window was previously hidden.
Also, the binding might create a retain cycle, so you should probably unbind it when the window is closed, unless you want to keep the window and controller around. Note that the window does post NSWindowWillCloseNotification when it's closing, so you don't need any special magic to detect that.
I have a NSWindow with an NSView and an NSTextField inside.
I'm using Interface builder right now. I have dropped the two controls on the default NSWindow and subclassed an NSView. I'm implementing the -drawRect method from NSView and I need to access to the content of NSTextField.
How do I refer to the instance of NSTextField from a method inside the NSView ?
Your NSWindow is (or should be) controlled by a window controller. In IB you create an outlet for the NSTextField in your window controller. Using the outlet, you can then refer to the NSTextField:
In your window controller .h file:
#property (strong) IBOutlet NSTextField *myTextField;
In your window controller .m file:
#synthesize myTextField;
From there you can in your controller:
[[self myTextField] setEditable: NO];
A point to note is that you do not access the controls in a window directly from that window as windows (and all Cocoa controls for that matter) are statically stored in a XIB/NIB file. All access to controls (UI elements) is channelled through controllers (NSWindowController, NSViewController) which in turn are capable of loading XIB/NIB files.
Apple provides various samples in their docs on how to do this.
I have an application that will load a couple of windows depending on which button is pressed. All except one of these open on the mainScreen (the screen in which the main window is open in). One of them (the preference window) opens on the first screen (the screen with the menu bar). I cannot understand way it is doing this, is there a way to change the screen that a NSWindow opens on?
I could not get toohtik's answer to work. What I ended up doing was subclassing NSWindow and then overriding constrainFrameRect: toScreen:. This will automatically open the new window on the "main screen" of the application.
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
{
AppDelegate *delegate = [[NSApplication sharedApplication] delegate];
return [super constrainFrameRect:frameRect toScreen:delegate.window.screen];
}
I dont't know why you have that behaviour but you can change it through initWithFrame method that takes NSScreen argument.
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:
I have saveWindowController (NSWindowController subclass object). I use initWithWindowNibName: method to init the controller.
I set File's owner in xib to SaveWindowController. I connect delegate (from window) to File's owner and window (from controller) to NSWindow in xib file.
[NSApp beginSheet:[self.saveWindowController window]
modalForWindow:[self window]
modalDelegate:nil didEndSelector:nil contextInfo:nil];
After executing this method I see modal window without titlebar and it appears not like normal sheet. It just appears in left bottom corner of first window.
Could you help me, what I'm doing wrong?
Do you have your SaveWindowController's window set to "Visible at Launch" in the XIB? You must uncheck that option, or your window will try to display as soon as the XIB is loaded, and will not be positioned correctly.
I had a lot of trouble before realizing I declared my sheet window in IB without title bar. Does yours has one? If not, check the "title bar" option.
B.