概要
- SwiftUIでアラートといえばalert(_:isPresented:actions:message:)を使用しますが、細かい調整のためNSAlertを使いたい場面があり、そのときの忘備録です。
OK
Button {
let alert = NSAlert()
alert.messageText = "Title"
alert.informativeText = "message"
alert.addButton(withTitle: "OK")
_ = alert.runModal()
} label: {
Text("OK")
}
OK / Cancel
Button {
let alert = NSAlert()
alert.messageText = "Title"
alert.informativeText = "message"
alert.addButton(withTitle: "OK")
alert.buttons[0].tag = NSApplication.ModalResponse.OK.rawValue
alert.addButton(withTitle: "Cancel")
alert.buttons[1].tag = NSApplication.ModalResponse.cancel.rawValue
let result = alert.runModal()
if result == .OK {
print("tapped: OK")
} else if result == .cancel {
print("tapped: Cancel")
} else {
print("tapped: Unknown")
}
} label: {
Text("Cancel / OK")
}
Delete / Cancel
- DeleteボタンにはhasDestructiveActionを使用する
Button {
let alert = NSAlert()
alert.messageText = "Title"
alert.informativeText = "message"
alert.addButton(withTitle: "Cancel")
alert.buttons[0].tag = NSApplication.ModalResponse.cancel.rawValue
alert.addButton(withTitle: "Delete")
alert.buttons[1].hasDestructiveAction = true
let result = alert.runModal()
if result == .cancel {
print("tapped: Cancel")
} else if result == .alertSecondButtonReturn {
print("tapped: Delete")
} else {
print("tapped: Unknown")
}
} label: {
Text("Cancel / Delete")
}
3つ以上のボタン
Button {
let alert = NSAlert()
alert.messageText = "Title"
alert.informativeText = "message"
alert.addButton(withTitle: "First")
alert.addButton(withTitle: "Second")
alert.addButton(withTitle: "Third")
let result = alert.runModal()
switch result {
case .alertFirstButtonReturn:
print("tapped: First")
case .alertSecondButtonReturn:
print("tapped: Second")
case .alertThirdButtonReturn:
print("tapped: Third")
default:
print("tapped: Unknown")
}
} label: {
Text("First / Second / Third")
}
- またボタンが4つ以上ある場合は下記の見た目になる(macOS 13)
ボタンのキー設定
- ボタンが2つあるとき、デフォルトでは左のボタンにEsc、右のボタンにEnterが割り当てられているよう。
- またキーは以下のように設定できる。
alert.buttons[0].keyEquivalent = "\r" // Enter
alert.buttons[0].keyEquivalent = "\u{1b}" // Esc
ボタン押下時にアラートを表示したままにする
- NSAlertダイアログのボタンを押下すると、ダイアログは終了してしまう。
- そこでtargetを設定すると表示したままにできる。
- またSwiftUIのViewはtargetに指定できないため、NSObjectを継承させたAlertManagerを定義してそこで処理を行っている。
struct ContentView: View {
let alertManager = AlertManager()
var body: some View {
VStack {
Button {
alertManager.handleAlertButtonTapped()
} label: {
Text("First / Second / OK")
}
}
.padding()
}
}
class AlertManager: NSObject {
func handleAlertButtonTapped() {
let alert = NSAlert()
alert.messageText = "Title"
alert.informativeText = "message"
alert.addButton(withTitle: "First")
alert.buttons[0].target = self
alert.buttons[0].action = #selector(self.handleFirstButtonTapped)
alert.buttons[0].keyEquivalent = ""
alert.addButton(withTitle: "Second")
alert.buttons[1].target = self
alert.buttons[1].action = #selector(self.handleSecondButtonTapped)
alert.addButton(withTitle: "OK")
alert.buttons[2].keyEquivalent = "\r"
let result = alert.runModal()
switch result {
case .alertThirdButtonReturn:
print("tapped: OK")
default:
print("tapped: Unknown")
}
}
@objc func handleFirstButtonTapped() {
print("handleFirstButtonTapped")
}
@objc func handleSecondButtonTapped() {
print("handleSecondButtonTapped")
}
}