2010-11-01 1 views
4

Моя цель: отобразить пользовательский лист с определенным NSProgressIndicator, в то время как приложение работает через длинный цикл. Я хочу, чтобы лист был прикладным, а не документально-модальным. Пользователь не может отклонить модальный лист. Они должны ждать, пока приложение завершит обработку цикла.Проблема с использованием пользовательского модального листа с какао

Проблема: я не могу получить пользовательский лист для прикрепления к окну. Он отображается как отдельное окно, в котором отсутствует строка заголовка окна (в виде листа). Кроме того, лист не отпускается (не закрывается), когда петля заканчивается.

У меня есть 2 отдельных файла-ниба для листа и главного окна приложения, а также 2 класса контроллера для каждого окна.

Вот необходимая информация: реализация контроллера для пользовательского листа:

@implementation ProgressSheetController //subclass of NSPanel 

-(void)showProgressSheet:(NSWindow *)window 
{ 
    //progressPanel is an IBOutlet to the NSPanel 
    if(!progressPanel) 
     [NSBundle loadNibNamed:@"ProgressPanel" owner:self]; 

    [NSApp beginSheet: progressPanel 
     modalForWindow: window 
     modalDelegate: nil 
     didEndSelector: nil 
      contextInfo: nil]; 

    //modalSession is an instance variable 
    modalSession = [NSApp beginModalSessionForWindow:progressPanel]; 

    [NSApp runModalSession:modalSession]; 
} 

-(void)removeProgressSheet 
{ 
    [NSApp endModalSession:modalSession]; 
    [NSApp endSheet:progressPanel]; 
    [progressPanel orderOut:nil]; 
} 

//some other methods 
@end 

Реализация главного окна приложения. Метод testFiles - это IBAction, подключенный к кнопке.

@implementation MainWindowViewController //subclass of NSObject 

-(IBAction)testFiles:(id)sender; 
{ 
    //filesToTest is a mutable array instance variable 
    int count = [filesToTest count]; 

    float progressIncrement = 100.0/count; 

    ProgressSheetController *modalProgressSheet = [[ProgressSheetController alloc] init]; 
    [modalProgressSheet showProgressSheet:[NSApp mainWindow]]; 

    int i, 
    for(i=0; i<count; i++) 
    { 
     //do some stuff with the object at index i in the filesToTest array 

     //this method I didn't show in ProgressSheetController.m but I think it's self explanatory 
     [modalProgressSheet incrementProgressBarBy:progressIncrement]; 
    } 
    //tear down the custom progress sheet 
    [modalProgressSheet removeProgressSheet]; 
    [modalProgressSheet release]; 
} 
@end 

Одна мысль: Я правильно подклассифицирую? Должен ли я использовать NSWindowController? Заранее спасибо за вашу помощь!

ответ

15

Найдено this gem сделать некоторые googling. Поведение моего NSPanel в Interface Builder было настроено на «Visible at Launch», которое по умолчанию используется для новых окон при использовании IB. Что случилось, как только загрузился наконечник, окно стало видимым до [NSApp beginSheet:...].Поэтому, сняв флажок «Видимый при запуске», я решил проблему, и теперь лист появляется, как я хочу, с окном.

1
@implementation ProgressSheetController //subclass of NSPanel 

-(void)showProgressSheet:(NSWindow *)window 
{ 
    //progressPanel is an IBOutlet to the NSPanel 
    if(!progressPanel) 
     [NSBundle loadNibNamed:@"ProgressPanel" owner:self]; 

Так что ваш NSPanel владеет другой NSPanel? Если вторая - панель прогресса, что показывает первая?

Должен ли я [подкласс] NSWindowController вместо этого?

Звучит так.

modalSession = [NSApp beginModalSessionForWindow:progressPanel]; 

Почему?

[modalProgressSheet showProgressSheet:[NSApp mainWindow]]; 

Вы проверили, что есть главное окно? mainWindow не возвращает окно, о котором вы больше всего заботитесь; он возвращает активное окно (что, вероятно, но необязательно, также ключ).

Если mainWindow возвращает nil, это может послужить причиной вашей проблемы.

int i, 
for(i=0; i<count; i++) 
{ 
    //do some stuff with the object at index i in the filesToTest array 

Во-первых, int неправильный тип. Вы должны использовать NSUInteger для индексов NSArray.

Во-вторых, если вам не нужен индекс для чего-то еще, вы должны использовать fast enumeration.

+0

Питер, спасибо за быстрый наконечник перечисления. Я заменил выражение «for» на «for (NSURL * fileURL в filesToTest)», потому что это то, что содержит массив. «[NSApp mainWindow]» не ноль. Я посыпал код NSLogs, чтобы узнать. Он передает правильное окно. Я не уверен, правильно ли я использую модальные сеансы. «beginModalSessionforWindow:» возвращает NSModalSession. Я сделал его ivar, чтобы мой метод removeProgressSheet: мог завершить модальный сеанс. Но даже если я удалю код модального сеанса, у меня все еще есть та же проблема. Хммм ... –

Смежные вопросы