gpt4 book ai didi

objective-c - 如何在 Cocoa 中显示和管理简单的应用程序模式对话框

转载 作者:太空狗 更新时间:2023-10-30 03:44:59 26 4
gpt4 key购买 nike

我不确定我做事的方式是否正确,或者我是否把一切都搞砸了。

我创建了一个非常简单的测试应用程序(不是基于文档的),用于学习如何在 Cocoa 应用程序中使用应用程序模式对话框。

对于应用程序项目“TestModalDialog”,我有一个简单的 MainMenu.xib,带有默认 View 和一个按钮,“显示对话框”,我添加了。我创建了第二个名为 TheDialog.xib 的 XIB,它具有“取消”和“确定”按钮。 xib 拥有一个从 NSWindowController 派生的名为“TheDialogController”的类;窗口导出和委托(delegate)连接到 Controller 。

在主视图上选择“显示对话框”将启动对话框。选择“取消”或“确定”将关闭对话框。这是非常简单的代码:

//  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 并进行测试之前,如果用户点击关闭按钮(左上角的红点),对话框将关闭但模态 session 仍在运行。

我意识到我可以直接将关闭按钮从对话框中移除,但是有了它,我所展示的是捕捉该场景的好方法,还是有更好的方法?或者,我是不是一开始就做错了什么,这给我带来了问题?

如有任何建议,我们将不胜感激。

注意 - 原始示例中的代码被注释掉并替换为基于答案的代码。还添加了一个新的通知处理程序。

最佳答案

okDialog:closeDialog: 方法中调用 close 而不是 performClose: 以避免窗口调用windowShouldClose: 委托(delegate)方法。这样你就不需要 userClickedCloseOrOk

此外,我认为您想调用 stopModalWithCode: 而不是 stopModal 因为在应用委托(delegate)中您似乎对结果感兴趣。你可以调用 stopModalstopModalWithCode: 而不是 abortModal 因为当你调用它时你总是在运行循环中(中止是当你在模式运行循环之外,比如在另一个线程或定时器的运行循环中)。

windowShouldClose: 中,您正在执行操作 (abortModal),此时您应该只回答“应该关闭此窗口”的问题。 windowWillClose: 委托(delegate)方法是您应该在需要时执行操作的地方。

工作表在只有一个窗口时很有用,它告诉用户在完成工作表中的任何内容之前不能使用它做任何事情。当您有多个窗口时,用户无法与之交互,直到他们完成模式窗口中的任何内容,或者存在涉及整个应用程序但与一个窗口的内容无关的错误时,应用程序模式窗口很有用。在他们的 HIG 中,Apple 建议尽可能避免使用应用程序模式窗口。

关于objective-c - 如何在 Cocoa 中显示和管理简单的应用程序模式对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9218598/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com