Preferences Window Problem (Once Open And Closed, Will Not Open Again) - cocoa

The problem I've got is that when the preferences window is opened and then closed, it will not open again. Why is this happening and how can this be fixed?
EDIT: Just noticed also I've got the same problem with Main Window.
The window is being opened via the menu bar and is in a separate NIB file.

It sounds like you forgot to set the 'window' outlet of your window controller (in the Nib, the File's Owner) to point to your window. Once you connect its 'window' outlet the window controller's showWindow: method will work.

Hard to say without seeing the code, but one possibility is that you have "Release When Closed" checked for the window in Interface Builder, and you are loading it once, caching it, then expecting to be able to close and re-open it without loading from the nib again.

For any other noobs like me, having this issue :)
Don't forget to set the file's owner class to be the same as the controller class, then you can connect the 'window' outlet to the panel.

I encountered this same problem while working on the chapter 12 (Nib Files and NSWindowController) exercise in Aaron Hillegass's Cocoa Programming for Mac OS X book. Doug's answer above was the solution - I hadn't linked the window outlet of the Preferences.xib's file owner to the window itself (in this case the Panel (Preferences) window).
I right clicked on the "File's Owner" in the Preferences.xib file then left-mouse-button dragged from the Window outlet to the Panel (Preferences). Once done and rebuilt the application worked as intended. I could close and reopen the custom preference panel and my previous settings were still there (since the preference window is not unloaded just hidden).

Related

Cocoa How to show another window instead of the main window

I create a cocoa application on OSX 10.8. I create a windows derived from NSWindowController and also create a .xib file for this window, I want to show this window when application start, so I add the following in the applicationDidFinishLaunching function
wndAgreement = [[AgreementWindow alloc] initWithWindowNibName:#"AgreementWindow"];
[wndAgreement showWindow:self];
But I still see the application's main window showing. Basically, the main window is behind my window. How to make the main window not show at all and only showing my window? The reason I am doing this is because I am building a wizard application, so click next on one window will open another window and close the current window.
The main window is probably showing because it's in the main menu NIB and has Visible At Launch enabled. "Visible At Launch" really means "visible when the NIB is loaded".
The quickest fix is to turn off Visible At Launch for that window. Better would be to remove that window from that NIB. Although it's the default behavior you get from Apple's project templates, it's a bad idea of have a window in your main menu NIB. They should all be done like your new window, with a separate NIB.
Go to the "Supporting Files" Folder of your project and click on the file that ends in "info.plist." Under "Main nib file base name," you will likely see "MainMenu." Delete this and enter the name of the window you want to show at launch.

Why cannot I open the Preferences from each windows?

I have come across this Cocoa application (source code) that shows a main Window.
As long as this window is key it is possible to open the Preferences window from the Main menu as well as by hitting Command-, but when the main window is not key and another window from the same app is, the NSMenuItem is grayed out and the keyboard shortcut does not respond.
I've inspected the xib file associated to the Main Menu and that NSMenuItem is sending a openPreferences:(id)sender IBAction to the FirstResponder which sould be the NSApplication.
What am I missing (I am still a newbie at mac cocoa programming)? How can I fix it so that the preferences are reachable from each application window?
Probably the original author implemented - (BOOL)validateMenuItem:(NSMenuItem *)menuItem and returns NO under some circumstances.
NSMenuValidationProtocol documentation.
Update: Another quick guess: Maybe the object that handles the IBAction for the menu item is not in the responder chain anymore after you open the second window. NSMenuItems are only enabled if the action selector can be found in the responder chain.

How can I display a hidden view in Interface Builder which is on a unattached monitor?

I am using Interface Builder to work on NIBs and one of the NIBs must have a view on my external monitor which is not attached because I cannot see it on my MacBook. I have had this problem with editing iPad NIBs which I work on with my larger external monitor.
For some reason Interface Builder is not detecting that there is now just one screen and not pulling this view onto this monitor. There has to be a way to get this back into the visible space so that I can work on it. I have tried double clicking on the view icon in the organizer which normally brings the view forward but it is not coming into view.
What can I do? Is this really a bug that has been around this whole time?
I was seeing this problem as well -- the easiest way to fix it is:
In Interface Builder, double-click on the view object. This would ordinarily bring up the window and give it focus, but in this case it's invisible.
Hit Cmd-W to "close" the invisible window
Double-click the view object again; the window should now re-open onscreen.
Yes - it messes up this way when a XIB is created on a computer with multiple monitors but then later edited on different computer with just one.
To my knowledge the only way to fix is to to open the XIB with a text, or ideally XML, editor and search for negative values in various positioning strings. I've searched for {{-and then changed any negative values found to 0. For example, you'll run across {{-237,172}} When you find the open brace, open brace, minus sign pattern then change the negative value to a zero. i.e. {{-237,172}} becomes {{0,172}}.
When you re-open the XIB in IB you'll then be able to see your views.
To be safe make a copy of the XIB before hand editing.
Try using Exposé to see if the window shows up there. Ordinarily you can use Window > Arrange in Front to rearrange your windows, but it seems the non-document windows in IB don't obey ordinary Cocoa window handling so this command has no effect on them.
I wasn't able to reproduce it myself (when I disconnected my 2nd monitor, the window on it moved to my main monitor), but it may have something to do with the arrangement of your screens. If this turns out to be an IB bug you can reproduce, please file it (bugreport.apple.com).
Not sure if this will work, but open the window from your xib (double-click it) in Interface builder, then go to the "Window Size" section of the inspector. 2 Places might help in there, first the "Initial Position" shows a representation of the window and you might be able to just drag it back to the proper place. Second is "Content Frame". There are "X and Y" settings so try changing them to 0 and see if that does it.
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>WhatEverYouNamedIT</string>
<string>UIResponder</string>
<string>{{237, 644}, {320, 480}}</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object
I opened the .xib file with Dashcode and changed the {{237, 644} to {{0, 172} saved and opened with IB and the view "canvas" windows was back on my laptop screen everything else opened up on my external monitor.
THANKS!!!

NSWindow delegate (windowShouldClose)

In one of my first Cocoa applications I have just a single window with 2 NSTextField instances - for user text input and of output of text processing.
If my user clicks on the red x on the top left, the window closes but the application is still running and icon stays in the dock - the normal Mac behavior.
When the user double-clicks on the icon in dock or on the desktop, this does not reopen the window - apparently also normal Mac behavior, but confusing to the user.
To get the app back into a running state, the user has to force Quit from the main menu or the context menu, and restart the app by clicking on one of the icons.
I searched Apple doc and forums, and it seemed that the following should prevent the closing of the window (my first preference : hide the widow so it can be reopened later) :
add a delegate to NSApp
delegate implements -applicationShouldHandleReopen which calls [mainWindow makeKeyAndOrderFront:self]; and returns TRUE
delegate implements -windowShouldClose which returns FALSE
However, although -windowShouldClose is called, the window closes.
What am I missing here?
As an alternative (my second preference), I added to the delegate
-applicationShouldTerminateAfterLastWindowClosed which returns YES
This works, i.e. the application closes when the used clicks on the red x,
and the user can restart the app later without further ado.
Clarifications and pointers to specific doc and working code examples would be appreciated.
Rudi
"When the user double-clicks on the icon in dock or on the desktop, this does not reopen the window - apparently also normal Mac behavior, but confusing to the user."
If you want the window to re-open in that case, implement applicationShouldHandleReopen:hasVisibleWindows:. There's nothing un-Mac-like about opening a window when the user clicks the dock icon after closing all the windows; lots of apps do it and the delegate exists specifically to support that behavior.
First of all, your "alternative" behavior of terminating the app on window close is probably the preferred approach for your situation. Users may be confused when they can't close the window.
If you really want to prevent the window from being closed, why not just disable the close control on the window in IB?

How to open a launch NSWindow in Cocoa on a button click

I have an NSWindow that I defined in interface builder. I want to make it so that when the user clicks a button, it opens a new instance that NSWindow. Do I have to subclass NSWindow or something?
If you created the window in IB and it's in your main nib file, you cannot create a "new instance" each time you press a button. When you create an object in the nib file, an instance is actually created by IB and then archived into the nib file, so you get that instance. Assuming your window is wired to a variable named auxWindow on the same object that responds to your button click, and the action message is named buttonClick, you could do something like this to show it:
-(IBAction)buttonClick:(id)sender {
if(! [auxWindow isVisible] )
[auxWindow makeKeyAndOrderFront:sender];
}
This will cause the aux window that you defined in IB to appear on the screen and become the key window (and foremost window in the application). Please note, however, that if you intend to reuse this window, you must uncheck the box in the IB Inspector that says Release on Close, otherwise you will get an access violation the next time you click the button.
This is a simple answer to your basic question, but window programming can be quite complicated and is usually very specific (for instance, do you really want a panel for what you're doing?)... so I strongly suggest that you read the Window Programming Guide for more information on this topic, and then ask very specific questions here when you get stuck.
Put the window in its own nib file, then load the nib file each time. You should use NSWindowController for loading the nib, like NSDocument does.

Resources