Как отображать простой диалог в модальном приложении и управлять им в Какао

Я не уверен, что делаю все правильно, или если у меня все это взломано .

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

В проекте приложения TestModalDialog у меня есть простой MainMenu.xib с представлением по умолчанию и кнопкой «Показать диалог», которую я добавил. Я создал второй XIB под названием TheDialog.xib с кнопками «Отмена» и «ОК». Этот xib имеет своим владельцем класс, производный от NSWindowController, под названием «TheDialogController»; оконный выход и делегат подключены к контроллеру.

Выбор «Показать диалог» на главном экране запускает диалог. Выбор «Отменить» или «ОК» закроет диалоговое окно. Вот довольно простой код:

//  TestModalDialogAppDelegate.h  
//  TestModalDialog  

#import <Cocoa/Cocoa.h>  

@class TheDialogController;  

@interface TestModalDialogAppDelegate : NSObject <NSApplicationDelegate>  
{  
  NSWindow *window;  
  TheDialogController* theDialogController;  
}  

@property (assign) IBOutlet NSWindow *window;  
- (IBAction)showDialog:(id)sender;  

@end  

//  TestModalDialogAppDelegate.m  
//  TestModalDialog  

#import "TestModalDialogAppDelegate.h"  
#import "TheDialogController.h"  

@implementation TestModalDialogAppDelegate  

@synthesize window;  

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification  
{  
  theDialogController= [[TheDialogController alloc] init];  
}  

- (void)dealloc  
{
  if(nil != theDialogController)   
    [theDialogController release];  

  [super dealloc];  
}  

- (IBAction)showDialog:(id)sender  
{  
  if(nil == theDialogController)  
  {  
    NSAlert* alert= [NSAlert alertWithMessageText:@"Dialog Error" defaultButton:nil alternateButton:nil otherButton:nil informativeTextWithFormat:@"The dialog controller was not allocated."];  
    [alert runModal];  
    return;  
  }

  NSInteger result= [NSApp runModalForWindow:[theDialogController window]]; 
  // Do something with result.... 
}  
@end  

//  TheDialogController.h  
//  TestModalDialog  

#import <Cocoa/Cocoa.h>  

@interface TheDialogController : NSWindowController  
{  
  // BOOL userClickedCloseOrOk; // Removed based on answer.  
  // Should declare a common define - just being lazy.  
  NSInteger userClickedOk;  // Added based on answer.  
  UInt16 timesShown;   
}  

- (IBAction)showWindow:(id)sender;  
- (IBAction)closeDialog:(id)sender;  
- (IBAction)okDialog:(id)sender;  
//- (BOOL)windowShouldClose:(id)sender;   // Removed based on answer.  
- (void)windowWillClose:(NSNotification*)notification;  // Added based on answer.   
- (void)windowDidBecomeKey:(NSNotification*)notification;  // To set title when modal.  
@end  

//  TheDialogController.m  
//  TestModalDialog  

#import "TheDialogController.h"  

@implementation TheDialogController  

- (id)init  
{  
  self = [super initWithWindowNibName:@"TheDialog"];  

  userClickedOk= 0;  // Added based on answer.  
  // userClickedCloseOrOk= FALSE;  // Removed based on answer.  

  return self;  
}  

-(void)dealloc  
{  
  // Do member cleanup if needed.
  [super dealloc];  
}  

- (void)windowDidLoad  
{  
  [super windowDidLoad];  

  // Initialize as needed....  
  [[self window] center];  // Center the window.  
}  

// Does not show with runModalForWindow.  
- (IBAction)showWindow:(id)sender  
{  
  // Just playing with the window title....  
  ++timesShown;  
  NSString* newTitle= [NSString stringWithFormat:@"Shown %d Times", timesShown];  
  [[self window] setTitle:newTitle];  
  return [super showWindow:sender];  
}  

// This method no longer used for this solution based on the answer.  
//- (BOOL)windowShouldClose:(id)sender  
//{  
//  if(!userClickedCloseOrOk)  // The user did not click one of our buttons.  
//    [NSApp abortModal];  
//  else  
//    userClickedCloseOrOk= FALSE;  // Clear for next time.  
//  
//  return TRUE;  
//}  

// Added based on answer.  
- (void)windowWillClose:(NSNotification*)notification  
{  
  [NSApp stopModalWithCode:userClickedOk];  
  userClickedOk= 0;  // Reset for next time.  
}  

// Note - the title will update every time the window becomes key. To do the  
// update only once per modal session, a flag can be added. There might be a better  
// notification to catch.  
- (void)windowDidBecomeKey:(NSNotification*)notification  
{  
  ++timesShown;  
  NSString* newTitle= [NSString stringWithFormat:@"Shown %d Times", timesShown];  
  [[self window] setTitle:newTitle];  
}  

- (IBAction)closeDialog:(id)sender  
{  
  //userClickedCloseOrOk= TRUE;  // Removed based on answer.  
  //[NSApp abortModal];  // Removed based on answer.  
  //[[self window] performClose:self];  // Removed based on answer.  
  [[self window] close];  // Know we want to close - based on answer.  
}  

- (IBAction)okDialog:(id)sender  
{  
  userClickedOk= 1;  // Added based on answer.  
  //userClickedCloseOrOk= TRUE;  // Removed based on answer.  
  //[NSApp stopModal];  // Removed based on answer.  
  //[[self window] performClose:self];  // Removed based on answer.  
  [[self window] close];  // Know we want to close - based on answer.  
}    

@end  

У меня были проблемы с модальностью - до того, как я ввел userClickedCloseOrOk и проверил, если пользователь нажмет кнопку закрытия (красная точка в верхнем левом углу), диалоговое окно закроется, но модальный сеанс все еще будет Бег.

Я понимаю, что могу просто оставить кнопку закрытия вне диалогового окна, чтобы начать с нее, но с ее помощью я продемонстрировал хороший способ уловить этот сценарий, или есть способ лучше? Или я с самого начала делаю что-то не так, что создает для меня эту проблему?

Любой совет будет признателен.

ПРИМЕЧАНИЕ - Код из исходного примера закомментирован и заменен кодом на основе ответа. Также добавлен новый обработчик уведомлений.

6
задан GTAE86 10 February 2012 в 18:02
поделиться