使用Swift创建NSAlert

56

我已经有用Objective-C创建NSAlert的代码,但现在我想用Swift创建。

这个警告框是为了确认用户是否要删除某个文档。

我希望“删除”按钮运行删除函数,“取消”按钮只是关闭警告框。

我该如何用Swift编写这个功能?

NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert addButtonWithTitle:@"Delete"];
[alert addButtonWithTitle:@"Cancel"];
[alert setMessageText:@"Delete the document?"];
[alert setInformativeText:@"Are you sure you would like to delete the document?"];
[alert setAlertStyle:NSWarningAlertStyle];
[alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil];

您可能需要考虑 beginSheetModal(for:completionHandler:)并没有被弃用,事实上这可能是处理模态对话框(在块中)更理想的方式。它也更接近具有 didEndSelector 的旧方式,并且不会停止整个应用程序。 - Patru
6个回答

154

beginSheetModalForWindow:modalDelegate在OS X 10.10 Yosemite中已被弃用。

Swift 2

func dialogOKCancel(question: String, text: String) -> Bool {
    let alert: NSAlert = NSAlert()
    alert.messageText = question
    alert.informativeText = text
    alert.alertStyle = NSAlertStyle.WarningAlertStyle
    alert.addButtonWithTitle("OK")
    alert.addButtonWithTitle("Cancel")
    let res = alert.runModal()
    if res == NSAlertFirstButtonReturn {
        return true
    }
    return false
}

let answer = dialogOKCancel("Ok?", text: "Choose your answer.")

根据用户的选择,这将返回truefalse

NSAlertFirstButtonReturn代表对话框中添加的第一个按钮,这里是“OK”按钮。

Swift 3

func dialogOKCancel(question: String, text: String) -> Bool {
    let alert = NSAlert()
    alert.messageText = question
    alert.informativeText = text
    alert.alertStyle = NSAlertStyle.warning
    alert.addButton(withTitle: "OK")
    alert.addButton(withTitle: "Cancel")
    return alert.runModal() == NSAlertFirstButtonReturn
}

let answer = dialogOKCancel(question: "Ok?", text: "Choose your answer.")

Swift 4

现在我们使用枚举来表示警告框的样式和按钮的选择。

func dialogOKCancel(question: String, text: String) -> Bool {
    let alert = NSAlert()
    alert.messageText = question
    alert.informativeText = text
    alert.alertStyle = .warning
    alert.addButton(withTitle: "OK")
    alert.addButton(withTitle: "Cancel")
    return alert.runModal() == .alertFirstButtonReturn
}

let answer = dialogOKCancel(question: "Ok?", text: "Choose your answer.")

4
请确保在 Swift 3 中至少导入 AppKit。 - Claude
2
@Claude 如果你正在制作一个警报,那意味着你正在制作一个Cocoa应用程序,并且这意味着你正在导入已经导入AppKit的Cocoa。 - Eric Aya
也许我不应该从非VC类中触发警报;但我只想要一些简单的错误显示。这个实用程序类除了Foundation之外没有导入任何东西,所以我需要这个导入(至少它让XCode感到高兴)。 - Claude
1
alert.alertStyle = .warning works in Swift 3 too, no need to add NSAlertStyle - zxcat
@EricAya 我该如何返回所点击按钮的文本? - Revel Carlberg West
显示剩余3条评论

26

我认为这可能适合您......

let a = NSAlert()
a.messageText = "Delete the document?"
a.informativeText = "Are you sure you would like to delete the document?"
a.addButtonWithTitle("Delete")
a.addButtonWithTitle("Cancel")
a.alertStyle = NSAlert.Style.WarningAlertStyle

a.beginSheetModalForWindow(self.view.window!, completionHandler: { (modalResponse) -> Void in
    if modalResponse == NSAlertFirstButtonReturn {
        print("Document deleted")
    }
})

NSAlert.Style.WarningAlertStyle you need a period between NSAlert and Style - tommed

11

更新Jose Hidalgo的Swift 4答案:

let a: NSAlert = NSAlert()
a.messageText = "Delete the document?"
a.informativeText = "Are you sure you would like to delete the document?"
a.addButton(withTitle: "Delete")
a.addButton(withTitle: "Cancel")
a.alertStyle = NSAlert.Style.warning

a.beginSheetModal(for: self.window!, completionHandler: { (modalResponse: NSApplication.ModalResponse) -> Void in
    if(modalResponse == NSApplication.ModalResponse.alertFirstButtonReturn){
        print("Document deleted")
    }
})

5

选择 @Jose Hidalgo 的答案,适用于 Swift 5

        let a = NSAlert()
        a.messageText = "Delete the document?"
        a.informativeText = "Are you sure you would like to delete the document?"
        //   .alertFirstButtonReturn
        a.addButton(withTitle: "Delete")

        //   .alertSecondButtonReturn
        a.addButton(withTitle: "Cancel")
        a.alertStyle = .warning
        var w: NSWindow?
        if let window = view.window{
            w = window
        }
        else if let window = NSApplication.shared.windows.first{
            w = window
        }
        if let window = w{
            a.beginSheetModal(for: window){ (modalResponse) in
                if modalResponse == .alertFirstButtonReturn {
                    print("Document deleted")
                }
            }
        }

1
在这里使用nil合并运算符会更加优美,像这样: if let window = view.window ?? NSApplication.shared.windows.first { alert.beginSheetModal(for: window) } - Antonin Charvat
视图未定义? - Gabriel
是的,代码在 NSViewController 中。 - dengST30

0

我尝试了上面的解决方案,但是我无法得到正确的警报大小。我已经定义了警报的大小。

        let alert = NSAlert()
        alert.messageText = "YOUR MESSAGE"
        alert.addButton(withTitle: "BUTTON1")
        alert.addButton(withTitle: "BUTTON2")
        var frame = alert.window.frame
        frame.size.height = 300
        frame.size.width = 200
        alert.window.setFrame(frame, display: true)
        
        let stackViewer = NSStackView(frame: NSRect(x: 0, y: 0, width: 200, height: 00))
        alert.accessoryView = stackViewer
        
        
        alert.beginSheetModal(for: self.view.window!, completionHandler: { (modalResponse) -> Void in
                if modalResponse == NSApplication.ModalResponse.alertFirstButtonReturn {
                    print("first btn")
                    
                }else{
                    print("second btn")
              
            }
        })

0
    let anAlert = NSAlert()
    anAlert.messageText = "Exit?"
    anAlert.informativeText = "Changes will not be saved!"
    anAlert.alertStyle = .warning
    anAlert.addButton(withTitle: "Yes")
    anAlert.addButton(withTitle: "No")
    if anAlert.runModal() == .alertFirstButtonReturn {
        return .terminateNow
    }
    return .terminateLater

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接