Expanding into many classes for my proj.

Discussion in 'Mac Programming' started by larswik, Jul 21, 2011.

  1. larswik, Jul 21, 2011
    Last edited: Jul 21, 2011

    larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #1
    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?
     
  2. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #2
    I had some typos that I got trying to copy pate around. Sorry.

    -Lars
     
  3. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #3
    Your AppController class doesn't have a property or a member named infoEntryWindow.
     
  4. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #4
    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.
     
  5. GorillaPaws macrumors 6502a

    GorillaPaws

    Joined:
    Oct 26, 2003
    Location:
    Richmond, VA
    #5
    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..
     
  6. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #6
    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.
     
  7. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #7
    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.
     
  8. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #8
    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
     
  9. GorillaPaws, Jul 22, 2011
    Last edited: Jul 22, 2011

    GorillaPaws macrumors 6502a

    GorillaPaws

    Joined:
    Oct 26, 2003
    Location:
    Richmond, VA
    #9
    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.
     
  10. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #10
    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!!!
     

Share This Page