Daniel
Daniel

Reputation: 3077

Cocoa, objective c NIB loading two times

I'm loading a Nib which contains a preference window using:

 PreferenceWindowViewController *pref = [[PreferenceWindowViewController alloc] init];
[NSBundle loadNibNamed:@"PreferenceWindow" owner:pref];

But the problem is that the user could easily click on the "preferences option" in the menu bar (File -> Preferences) again without closing the current open preference window, i was thinking of a boolean variable to be set to true once the nib is opened, but was unsure how to re set the boolean variable to false (Nib not loaded) which exists in the main class when the close the window in the preference view controller class

Upvotes: 0

Views: 546

Answers (3)

NSGod
NSGod

Reputation: 22948

This is usually how I do preferences. Your preferences controller class is custom NSWindowController subclass. In your main app controller, you create an instance variable for your prefs controller as shown below.

MDAppController.h:

@class MDPrefsController;

@interface MDAppController : NSObject <NSApplicationDelegate> {
     MDPrefsController  *prefsController;
}
- (IBAction)showPrefsWindow:(id)sender;
@end

MDAppController.m:

#import "MDAppController.h"
#import "MDPrefsController.h"

@implementation MDAppController
- (void)dealloc {
    [prefsController release];
    [super dealloc];
}

- (IBAction)showPrefsWindow:(id)sender {
    if (prefsController == nil)
          prefsController = [[MDPrefsController alloc] init];
[prefsController showWindow:self];
}
@end

You have the Preferences menu item set to call a method like -showPrefsWindow:. In that method, you first check to see if your prefsController instance variable is nil, and if it is, you create it using alloc/init. (Note: an instance variable like prefsController here is automatically initialized to nil during MDAppController's -init method). After assuring that the prefsController exists, you send it the standard NSWindowController method -showWindow:

MDPrefsController.h:

@interface MDPrefsController : NSWindowController <NSToolbarDelegate> {
    
}

@end

MDPrefsController.m:

#import "MDPrefsController.h"

@implementation MDPrefsController
- (id)init {
    if ((self = [super initWithWindowNibName:@"MDPrefs"])) {

    }
    return self;
}

- (IBAction)showWindow:(id)sender {
    if (![[self window] isVisible]) {
        [[self window] center];
    }
    [[self window] makeKeyAndOrderFront:nil];
}
@end

So by making your prefsController an instance variable, you can check to make sure it's only created once. Also, the user is free to select Preferences from the application menu any time they want, and the result is the preference's window being brought forward.

[EDIT] I'll add more information on how this setup assures that only one copy of the preferences window is created.

First, we should clarify what the desired behavior should be when the user chooses the Preferences… menu item from the application menu. When the user chooses the prefs menu item, if the single prefs window is not currently shown, it should be made visible. If, on the other hand, the prefs window is already visible, then it should be brought forward. For the most part, this menu item should be enabled at all times. (In other words, even if the prefs window is currently being shown, the menu item is still enabled. When chosen, it merely brings the prefs window forward).

The code I posted accomplishes the goals set forth above by making prefsController an instance variable, and assuring that it's only created once. The prefsController is an instance of MDPrefsController, which is a subclass of NSWindowController. An NSWindowController manages a single window that is generally stored in a nib file. In your example, you were handling the nib-loading code in your main controller using NSBundle. In mine, I factor that out into the MDPrefsController class, which will load the "MDPrefs.nib" file as specified in its -init method. (MDPrefsController overrides -init to call NSWindowController's -initWithWindowNibName:). That nib file contains the single window that the MDPrefsController manages.

The code shown below checks to make sure only that only a single instance of the MDPrefsController is ever created, and as such, assures that the MDPrefs.nib file, which contains the single preferences window, is only loaded once:

- (IBAction)showPrefsWindow:(id)sender {
    if (prefsController == nil)
          prefsController = [[MDPrefsController alloc] init];
[prefsController showWindow:self];
}

As a result, you assure that there's only a single copy of the prefs window.

[EDIT 2]: sample project at http://www.markdouma.com/developer/PreferencesWindow.zip

Upvotes: 1

just disable the File -> Preferences option, but not hide, until close the old one ,then enable that option.

Upvotes: 0

Joris
Joris

Reputation: 6305

Why don't you just load the window once at app startup and then do:

[pref showWindow:nil];

every time the user clicks on your menu item. Wouldn't that be easier?

Upvotes: 1

Related Questions