I have two .xib files, MainMenu and PreferenceMenu. I set the File's Owner of PreferenceMenu to be a subclass of NSWindowController, so that I can modify how the window is opened, modified, etc.
Normally I open PreferenceMenu through IB, sending the showWindow: action to the Preferences Controller object. This has been working fine, and the window has been opening flawlessly. I also implemented NSTabView and NSToolBar in my PreferenceMenu as different tabs house different preferences.
Anyways, I now have to prompt the user if they want to open up the PreferenceMenu after first loading the application. My process is check to see if a NSUserDefaults key is set, then prompts and sets the key if it isn't. If the returned NSAlert button is a specific button, I then open up PreferenceMenu and switch to the correct tab.
The gist of this process is to:
- Import
CCPreferencesController.hinCCAppDelegate.h - Create a
strongreference to theCCPreferencesControllerwindow (for ARC) Prompt with
NSAlert, and if returned button is correct, run the following:self.windowController = [[CCPreferencesController alloc] initWithWindowNibName:@"PreferenceMenu"]; [self.windowController showWindow:self];Import
CCAppDelegate.hinCCPreferencesController.mDeal with the
NSAlertresponse inCCPreferencesController.m:- (void)showWindow:(id)sender{ if ([CCAppDelegate class] == [sender class]){ [self openLogin]; } [super showWindow:sender]; }- Switch the
TabViewin theopenLoginmethod.
This more of less works fine, except showWindow is called before the window's contents have actually loaded. This means that calling self.toolbar, self.tabView, etc. returns NULL. My solution to this is to simply use a timer to wait for the elements to load, but this is nowhere near elegant.
My question, therefore, is how can I avoid having to use a delay, and instead have my openLogin method get called on showWindow but wait for the window's contents to be loaded?
I'm also 99% sure that my code is awful, including how I'm importing .h files and subclassing File's Owner, so any tips to make this better are greatly appreciated.
For those who want to see the code in more detail, here are the relevant parts
CCAppDelegate.h:
#import <Cocoa/Cocoa.h>
#import "CCPreferencesController.h"
@class WebView;
@interface CCAppDelegate : NSObject <NSApplicationDelegate, NSUserNotificationCenterDelegate, NSSharingServiceDelegate>
@property (strong) CCPreferencesController *windowController;
...
@end
CCAppDelegate.m:
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame{
bool loginPrompted = [[NSUserDefaults standardUserDefaults] boolForKey:@"loginPrompted"];
if (!loginPrompted){
NSAlert *alert = [NSAlert alertWithMessageText:@"Login"
defaultButton:@"Login"
alternateButton:@"Cancel"
otherButton:nil
informativeTextWithFormat:@"Would you like to login to enable voting?"];
// Display alert
[alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
// Return focus to window
[[alert window] orderOut:self];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setBool:YES forKey:@"loginPrompted"];
[prefs synchronize];
if (returnCode == 1){
self.windowController = [[CCPreferencesController alloc] initWithWindowNibName:@"PreferenceMenu"];
[self.windowController showWindow:self];
}
}];
}
}
CCPreferencesController.h:
#import <Cocoa/Cocoa.h>
@interface CCPreferencesController : NSWindowController {}
...
@end
CCPreferencesController.m
#import "CCPreferencesController.h"
#import "CCAppDelegate.h"
@implementation CCPreferencesController
- (id)init{
if(self = [super initWithWindowNibName:@"PreferenceMenu"]) {}
return self;
}
- (void)awakeFromNib{
...
[self.toolbar setSelectedItemIdentifier:@"general"];
}
- (void)showWindow:(id)sender{
if ([CCAppDelegate class] == [sender class]){
[self openLogin];
}
[super showWindow:sender];
}
// This is gross
- (void)openLogin{
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 0.1);
dispatch_after(delay, dispatch_get_main_queue(), ^(void){
[self.toolbar setSelectedItemIdentifier:@"tab"];
[self.tabView selectTabViewItemAtIndex:1];
NSRect frame = [self.window frame];
frame.size.height += 55;
frame.origin.y -= 55;
[self.window setFrame:frame display:YES animate:YES];
});
}
windowDidLoadseems to be like the way to go, but how can I make sure that the request is coming from the alert and not form the menu?showWindowat least has thesenderid to query - Charlie