Доступ к главному окну из класса NSDocument

У меня есть класс NSDocument, где мне нужно получить доступ к окну главного меню, которое открывается при запуске приложения. Когда я работаю в этом окне из приложения, кажется, что все работает, но при попытке выполнить те же операции из readFromFileWrapper:ofType:error: окно, к которому я обращаюсь, кажется нулевым. Почему это происходит?

РЕДАКТИРОВАТЬ: некоторый код, который имеет дело с этим:

- (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;
    }
}

Это мой метод readFromFileWrapper:ofType:error:. Вот мой метод openProject:type::

-(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]); возвращает nil, тогда как MainWindow должно быть главным окном приложения. Я думаю, проблема в том, что двойной щелчок по файлу перераспределяет все и, следовательно, терпит неудачу.


person pmerino    schedule 08.01.2012    source источник
comment
Пожалуйста, опубликуйте свой код, чтобы мы могли точно понять, что вы делаете, что работает неправильно.   -  person Andrew Madsen    schedule 08.01.2012
comment
Проблема в том, что я не знаю, какой именно код публиковать. я попытаюсь   -  person pmerino    schedule 08.01.2012
comment
Любые подсказки с кодом, который я только что опубликовал?   -  person pmerino    schedule 08.01.2012
comment
Где вы инициализируете/настраиваете MainWindow? Кроме того, MainWindow, вероятно, следует называть mainWindow. Плохой стиль — использовать заглавные буквы в именах переменных. Имена классов (например, NSString) обычно пишутся с заглавной буквы. Когда вы пишете имена переменных с заглавной буквы, ваш код становится трудным для чтения и понимания, потому что это делает их похожими на имена классов.   -  person Andrew Madsen    schedule 08.01.2012
comment
MainWindow — это выход, подключенный к окну в MainMenu.xib. Насчет нейминга, да, думаю, лучше было бы так назвать, но написал в спешке и не успел переделать :)   -  person pmerino    schedule 08.01.2012
comment
Я опубликовал ответ, который, надеюсь, поможет. Тем не менее, пункт об именовании выхода MainWindow довольно важен, поэтому было бы неплохо изменить его. Стиль кода — это не то, на что компилятор жалуется, но это важная часть хорошего программиста.   -  person Andrew Madsen    schedule 08.01.2012


Ответы (2)


Не совсем понятно, что вы спрашиваете. Вы упоминаете, что MainWindow является выходом в MainMenu.xib, но не указываете, какой класс определяет выход.

Если это окно спроектировано так, чтобы иметь одно главное окно «проекта», вам следует назначить свойство выхода в вашем делегате приложения.

Затем вы можете получить к нему доступ из других классов, используя что-то вроде [(YourAppDelegate*)[NSApp delegate] mainWindow];.

Однако если вы пытаетесь получить ссылку на окно текущего документа, то это немного сложнее.

Причина, по которой NSDocument не имеет выхода window по умолчанию, заключается в том, что он предназначен для работы с экземплярами NSWindowController, которые сами управляют различными окнами, связанными с документом. Это делается для того, чтобы документ мог иметь несколько окон, показывающих разные виды одних и тех же данных, дополнительные палитры, связанные с документом, и т. д. Каждый экземпляр NSWindowController будет иметь свой собственный файл оконного пера и выход window.

По умолчанию NSDocument создает для вас один экземпляр NSWindowController, если вы специально не создаете и не назначаете NSWindowController экземпляров документу. Это происходит автоматически, вам даже не нужно знать о существовании оконного контроллера.

Это означает, что если вы не управляете своими окнами документов с экземплярами NSWindowController самостоятельно, вы можете прикрепить окно к NSWindowController, которое автоматически создается NSDocument следующим образом:

/* 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;
}
person Rob Keniger    schedule 08.01.2012

Обычный способ справиться с этим — добавить IBOutlet в ваш подкласс NSDocument, а затем подключить его к окну документа в файле .xib.

В вашем .h:

@interface MyDocument : NSDocument

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

@end

В вашем .м:

@implementation MyDocument : NSDocument

@synthesize docWindow;

@end

Затем, самая важная часть, откройте MyDocument.xib (или как там он называется) и перетащите соединение из File's Owner (при условии, что это ваш подкласс NSDocument, которым он является по умолчанию) в главное окно документа и подключите его к выход docWindow.

person Andrew Madsen    schedule 08.01.2012
comment
Если вы действительно сделали это, и это не работает, боюсь, я не могу сказать, что не так, не увидев больше вашего кода и/или ваших файлов .xib. - person Andrew Madsen; 08.01.2012