Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
I might as well ask this now. I am running a test to have my program use many classes to work together. But something is going wrong right away. I have an appDelegate class that was created with an NSWindow in it. I added a simple NSButton in the first window. I created a second NSWindow within the appDelegate as well. I then created my AppController class and assigned my 1 button to it. In the appController class I added the #import for my appDelegate class so I can access it's methods.

Then in the IBAction Method for the 1 button I asked it to open up the second NSWindow. I get an error "Use of undeclared identifier

appDelegate.h
Code:
#import <Cocoa/Cocoa.h>

@interface testTwoClassesAppDelegate : NSObject <NSApplicationDelegate> {
@private
    NSWindow *window;
    NSWindow *infoEntryWindow;
}

@property (assign) IBOutlet NSWindow *window;
@property (assign) IBOutlet NSWindow *infoEntryWindow;


@end
appDelegate.m
Code:
#import "testTwoClassesAppDelegate.h"

@implementation testTwoClassesAppDelegate

@synthesize window;
@synthesize infoEntryWindow;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
}


@end
AppController.h
Code:
#import <Foundation/Foundation.h>
#import "testTwoClassesAppDelegate.h"


@interface AppController : NSObject {
@private
    
}
- (IBAction)NewEnteryButton:(id)sender;

@end
AppController.m
Code:
#import "AppController.h"
#import "testTwoClassesAppDelegate.h"


@implementation AppController


- (IBAction)NewEnteryButton:(id)sender {
    [infoEntryWindow makeKeyAndOrderFront:self];
}
@end
main.m
Code:
#import <Cocoa/Cocoa.h>

int main(int argc, char *argv[])
{
    return NSApplicationMain(argc, (const char **)argv);
}

What am I doing wrong?
 
Last edited:
I had some typos that I got trying to copy pate around. Sorry.

-Lars
 
Thanks gnasher729.

After I posted I began to realize a few things. 1 I think I need to instantiate that class to use it like this.

AppController.m
Code:
#import "AppController.h"
#import "testTwoClassesAppDelegate.h"


@implementation AppController

- (IBAction)NewEnteryButton:(id)sender {
    testTwoClassesAppDelegate * testObject = [[testTwoClassesAppDelegate alloc]init];
    [testObject newWindowOpen];
    [testObject release];
}
@end

appDelegate.m
Code:
#import "testTwoClassesAppDelegate.h"

@implementation testTwoClassesAppDelegate

@synthesize window;
@synthesize infoEntryWindow;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
}

-(id)newWindowOpen{
    [infoEntryWindow makeKeyAndOrderFront:self];
    return self;
}
@end

The program now runs and the fiorst window pops up but when I press teh second button the second window does not pop up, yet. I hope I am on the right past here.

Thanks again for putting up with my slow learning.
 
Your second window should have it's own window controller that manages it. Your app delegate should tell the secondary window controller that it needs a new window (the less your app controller knows about the details of your secondary window the better), and then the secondary window should encapsulate all of the functionality of opening the second window and managing all of its content..
 
Thanks GorillaPaws. I just want to talk it through so I am sure I am doing the right thing. So when you say it should have it's own window controller your talking about going in to the xib by dragging out a new blue object box. I then need to assign that object to a new class I create for the window, or an existing one like the AppController? This is the part I am a little fuzzy on.

Thanks again.
 
Thanks GorillaPaws. I just want to talk it through so I am sure I am doing the right thing. So when you say it should have it's own window controller your talking about going in to the xib by dragging out a new blue object box. I then need to assign that object to a new class I create for the window, or an existing one like the AppController? This is the part I am a little fuzzy on.

Thanks again.

When you use a XIB with a window controller, typically the XIB's file's owner is the window controller.

In the code where you want to open the second window, you instantiate the window controller using initWithWindowNibName:. I typically have the NSWindowController subclass override init to call initWithWindowNibName: with the correct XIB name, so other class just calls init.
 
That clears up a little bit. I am also reading through this doc right now. I hope it is not outdated.

http://developer.apple.com/library/...ual/LoadingResources/CocoaNibs/CocoaNibs.html

There are some missing pieces I need to read that I should familiar with that I am not. I might be using them and not knowing what they mean.
Things I see often.

1) Sub Classing.
2) Controllers (I can make a NSbutton, drag in an object box from the library, then File -> New to create a new class, then assign my blue object box to the new class, then control drag the NSButton and other things to make IBOutlets and IBActions). But what part of that is refereed to as the controller I don't know, yet?

So when you say "XIB's file's owner is the window controller." I think of the new class I just created as the window controller class.

Sorry, these are basic questions I should now the answer to by now. I'll keep reading the Nib document.

Thanks
 
2) Controllers (I can make a NSbutton, drag in an object box from the library, then File -> New to create a new class, then assign my blue object box to the new class, then control drag the NSButton and other things to make IBOutlets and IBActions). But what part of that is refereed to as the controller I don't know, yet?

So when you say "XIB's file's owner is the window controller." I think of the new class I just created as the window controller class.

You've got this pretty much right. Basically, in code you're going to create a new class called LARSPreferenceWindowController (or something like that), and make it a subclass of NSWindowController. You'll put the code for instantiating your preferences window and managing all of your views/controls for just that preferences window in there such as buttons and text fields etc. You'll also drag out a NSWindowController in the XIB file, change it to be a LARSPreferenceWindowController and wire your controls to it there.

What @jiminaus was saying was in the method in your app delegate that launches the preferences window to open, you're going to instantiate your LARSPreferenceWindowController object--say in the openPreferences method that gets called from pushing the preferences button or selecting "preferences" from the menu, etc., which will trigger the initWithWindowNibName: method in your LARSPreferenceWindowController object that will open your preferences XIB.

From an OOP point of view this structure is nice because the app delegate doesn't need to know much of anything about the preferences window or what it's doing, it just says "hey LARSPreferencesWindowController, make me a preferences window and do your thing." From here, the LARSPreferencesWindowController can encapsulate all of the functionality of managing the content of that preferences window without the app delegate needing to get involved.

Here's what's nice about this setup. Let's say down the road you want to change how your preferences works. All you need to do is make the changes in the LARSPreferenceWindowController class, and things should work out dandy, whereas if the app delegate was managing these details, then you're going to be making changes all over the place. For a smaller project this is less noticeable and is why many of the test apps and tutorials tend to be structured with throwing everything into the app delegate (and makes it harder for people like us trying to learn to see how larger projects should really be structured), and while the God Object anti-pattern may work well for tutorials (because it helps keep things more compact) it's not going to scale and isn't a reasonable strategy going forward.
 
Last edited:
GorillaPaws - thanks for that detailed explination. With Jim's response in another post I hope to move past this hang up I have with it.

One thing I noticed was I was making everything a child of the NSObject. In this case you used the NSWindowController.

Thanks again for taking the time!!!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.