可以在Cocoa中创建没有按钮的NSAlert

问题描述 投票:0回答:6

我是可可的新手。我想在可可中创建一个与 iOS 中相同的消息框,没有任何按钮。 NSTimer 之后消息框自动关闭。我使用下面的代码,但它总是添加“确定”按钮。

alert = [[[NSAlert alloc] init] autorelease];
// [alert addButtonWithTitle: @"OK"];
[alert setMessageText: @"Attention!!! This a critical Alert."];
[alert setInformativeText:@"Scanning..."];
[alert setAlertStyle: NSInformationalAlertStyle];

NSTimer *myTimer = [NSTimer timerWithTimeInterval: 17.0
                                           target:self
                                         selector: @selector(killWindow:) userInfo:nil
                                                             repeats:NO];

[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSModalPanelRunLoopMode];

int choice = 0;
choice = [alert runModal];
if(choice != 0)
    [myTimer invalidate];

KillWindow函数:

-(void) killWindow: (NSTimer *) theTimer
{
    NSLog(@"killWindow");
    [[alert window] close];
}

当警报关闭时,我的应用程序无法单击任何按钮或交互?

objective-c macos cocoa
6个回答
6
投票

也许在2013年答案是否定的。然而,在当前的 SDK (Xcode 7.0 with OS X 10.11) 中,您可以简单地通过 addButtonWithTitle("") 添加“”,然后按钮将不会显示。


2
投票

是的,你可以,你添加新按钮。之后,你得到它并隐藏它:)。我的代码

NSAlert* alert = [[NSAlert alloc] init];
[alert setMessageText:@"Loading...."];
[alert addButtonWithTitle:@"Cancel"];
NSButton *button =  [[alert buttons] objectAtIndex:0];
[button setHidden:YES];
[alert setAccessoryView:[self viewLoadingReadFile]];
[alert setAlertStyle:NSWarningAlertStyle];
[alert runModal];

1
投票

NSAlert 设计用于应用程序或窗口模式显示消息,并带有用于用户关闭的按钮。 它不是为显示没有按钮的窗口而设计的;你不应该这样使用它。

您应该使用自定义 NSWindow/NSPanel。 如果您希望它阻止窗口/应用程序,那么您将需要运行自己的模式会话。 除了像上面那样关闭窗口之外,还可以使用

abortModal
从计时器回调中停止模态会话。 这解释了为什么当警报关闭时您没有收到任何进一步的事件 - 模式会话仍在运行。

请参阅模态窗口如何工作了解更多信息。


0
投票

你应该看看

MBProgressHUD
。我使用
MBProgressHUD
解决这个问题。

+ (void)showMessage:(NSString *)message forDuration:(NSTimeInterval)duration withTitle:(NSString *)title
{
    UIWindow *window     = [UIApplication sharedApplication].keyWindow;
    MBProgressHUD *hud   = [MBProgressHUD showHUDAddedTo:window animated:YES];
    hud.mode             = MBProgressHUDModeText;
    hud.labelText        = title;
    hud.detailsLabelText = message;

    hud.removeFromSuperViewOnHide = YES;
    [hud hide:YES afterDelay:duration];
}

经过一些用户测试,确定用户不喜欢他们无法忽略的长时间消息。

+ (void)showMessage:(NSString *)message forDuration:(NSTimeInterval)duration withTitle:(NSString *)title
{
    if (duration < 3.0) {
        UIWindow *window     = [UIApplication sharedApplication].keyWindow;
        MBProgressHUD *hud   = [MBProgressHUD showHUDAddedTo:window animated:YES];
        hud.mode             = MBProgressHUDModeText;
        hud.labelText        = title;
        hud.detailsLabelText = message;

        hud.removeFromSuperViewOnHide = YES;
        [hud hide:YES afterDelay:duration];
    } else {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
                                                            message:message
                                                           delegate:nil
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
        [alertView show];

        int64_t delayInSeconds = duration;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [alertView dismissWithClickedButtonIndex:alertView.cancelButtonIndex animated:YES];
        });
    }
}

0
投票

关闭警报窗口后,您还必须使用 [NSApp abortModal] 中止模式

现在只需隐藏该按钮即可。为此,在实例化警报后,您可以在所有alert.window.contentView.subviews中扫描标题为“OK”的 NSButton 并将其隐藏。

免责声明:这是一个快速、丑陋的黑客攻击,但它目前有效。使用需要您自担风险


0
投票

在 MacOS 解决方案中添加一个 Swift,基于 @Lê Tấn Thành

的想法
func showAlertOnTask(task: @escaping () -> Any, alert_msg: String, parent_window:NSWindow) {
    let alert = NSAlert()
    alert.alertStyle = NSAlert.Style.warning
    alert.messageText = alert_msg
    alert.addButton(withTitle: "OK")
    let btn = alert.buttons[0]
    btn.isHidden = true
    
    DispatchQueue.main.async {
        task()
        alert.window.close()
    }
    
    alert.beginSheetModal(for: parent_window) // you can change to alert.runModal()
}

例如,当按下 GUI 中的按钮(让我们将其参数名称称为

btnLoad
)时,您会运行一个很长的任务。按钮操作将调用函数
long_task()

@IBAction func generate_plist(_ sender: Any) {
        showAlertOnTask(task: long_task(), alert_msg: "Loading...", parent_window: self.btnLoad.window!)
    }
© www.soinside.com 2019 - 2024. All rights reserved.