Access main window from a NSDocument class

4k Views Asked by At

I have a NSDocument class, where I'd need to access the main menu window, the one that gets opened when the app start. When I operate in that window from the app all seems to work, but when trying to do the same operations from readFromFileWrapper:ofType:error: the window I access seems to be nil. Why this happens?

EDIT: Some code which deals with this:

- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError **)outError
{
    if([[NSFileManager alloc] fileExistsAtPath:[NSString stringWithFormat:@"%@/Project.plist",[[self fileURL] path]]]) {
        NSLog(@"%@", [[self fileURL] path]);

        NSDictionary *project = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Project.plist",[[self fileURL] path]]];

        if([[project objectForKey:@"type"] isEqualToString:@"vote"]) {

            [self openProject:[[self fileURL] path] type:@"vote"];

            return YES;

        } else if([[project objectForKey:@"type"] isEqualToString:@"quiz"]) {

            [self openProject:[[self fileURL] path] type:@"quiz"];

            return YES; 

        } else {
            return NO;
        }
    } else {
        return NO;
    }
}

That is my readFromFileWrapper:ofType:error: method. Here is my openProject:type: method:

-(void)openProject:(NSString *)filepath type:(NSString *)type 
{
    NSLog(@"Opening project @ %@",filepath);
    NSLog(@"%@", [MainWindow description]);
    [projectDesignerView setFrame:[[[[MainWindow contentView] subviews] objectAtIndex:0] frame]];
    [projectDesignerToolbar setFrame:[MainWindow frame] display:FALSE];
    [[MainWindow contentView] replaceSubview:[[[MainWindow contentView] subviews]objectAtIndex:0] with:projectDesignerView];
    [[projectDesignerToolbar toolbar] setShowsBaselineSeparator:YES];
    [MainWindow setToolbar:[projectDesignerToolbar toolbar]];
    [MainWindow setRepresentedFilename:filepath];
    [MainWindow setTitle:[NSString stringWithFormat:@"%@ - %@", [[filepath lastPathComponent] stringByDeletingPathExtension], [projectDesignerToolbar title]]];
    NSString *path = [[NSBundle mainBundle] pathForResource:@"projectDesigner" ofType:@"html"];
    NSURL *url = [NSURL fileURLWithPath:path];
    [[projectDesignerWebview mainFrame] loadRequest:[NSURLRequest requestWithURL:url]];
}

NSLog(@"%@", [MainWindow description]); returns nil, when MainWindow should be the Main App Window. I think the problem is that double-clicking on a file reallocs all, and hence is failing.

2

There are 2 best solutions below

0
On BEST ANSWER

It's not entirely clear what you're asking. You mention that MainWindow is an outlet in MainMenu.xib but you don't specify what class is defining the outlet.

If this window is designed to have a single main "project" window then you should assign the outlet property in your application delegate.

You can then access this from other classes using something like [(YourAppDelegate*)[NSApp delegate] mainWindow];.

If, however, you are trying to obtain a reference to the window of the current document then it's a little bit more complicated.

The reason that NSDocument does not have a window outlet by default is that it is designed to work with instances of NSWindowController that themselves manage the various windows related to the document. This is so a document can have multiple windows showing different views of the same data, additional palettes related to the document and so on. Each instance of NSWindowController would have its own window nib file and window outlet.

By default, NSDocument creates a single instance of NSWindowController for you if you do not specifically create and assign NSWindowController instances to the document. This is automatic, you don't need to even know the window controller exists.

That means that if you aren't managing your document windows with NSWindowController instances yourself, you can get the window attached to the NSWindowController that is automatically-created by NSDocument like so:

/* Only implement this in an NSDocument instance where the 
   automatic window controller is being used.
   If the document has multiple window controllers, you must
   keep track of the main window controller yourself
   and return its window
*/
- (NSWindow*)documentWindow
{
    if([[self windowControllers] count] == 1)
    {
        return [[[self windowControllers] firstObject] window]; 
    }
    return nil;
}
1
On

The normal way to handle this is to add an IBOutlet to your NSDocument subclass, then hook it up to the document window in the .xib file.

In your .h:

@interface MyDocument : NSDocument

@property (nonatomic, assign) IBOutlet NSWindow *docWindow;

@end

In your .m:

@implementation MyDocument : NSDocument

@synthesize docWindow;

@end

Then, the most important part, open up MyDocument.xib (or whatever it's called), and drag a connection from File's Owner (assuming that's your NSDocument subclass, which it is by default) to the main document window, and hook it up to the docWindow outlet.