Create an NSAlert with Swift

SwiftCocoaNsalert

Swift Problem Overview


I have the code to create and NSAlert in Objective-C but I would now like to create it in Swift.

The alert is to confirm that the user would like to delete a document.

I would like the "delete" button to then run the delete function and the "cancel" one just to dismiss the alert.

How can I write this in 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];

Swift Solutions


Solution 1 - Swift

beginSheetModalForWindow:modalDelegate is deprecated in 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.")

This returns true or false according to the user's choice.

NSAlertFirstButtonReturn represents the first button added to the dialog, here the "OK" one.

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

We now use enums for the alert's style and the button selection.

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.")

Solution 2 - Swift

I think this may work for you...

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")
    }
})

Solution 3 - Swift

Updated Jose Hidalgo's answer for 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")
    }
})

Solution 4 - Swift

opt @Jose Hidalgo's answer for 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")
                }
            }
        }

Solution 5 - Swift

I tried above solutions but I was not able to get proper size of alert. I have defined size of alert too.

        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")
              
            }
        })

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTom CoomerView Question on Stackoverflow
Solution 1 - SwiftEric AyaView Answer on Stackoverflow
Solution 2 - SwiftJose HidalgoView Answer on Stackoverflow
Solution 3 - SwiftJamie BirchView Answer on Stackoverflow
Solution 4 - SwiftdengST30View Answer on Stackoverflow
Solution 5 - SwiftLakshmi YadavView Answer on Stackoverflow