Reputation: 1269
I am trying to write a method in a UtilityController Class for NSAlerts, but the method is not displaying the alert. I am calling it from the viewDidAppear() method in my ViewController, so I assumed this would work since the view would already be on the screen. Right?
The reason I am calling this from the viewDidAppear() method is because in my actual application I am initially loading data from CoreData, which is called from the viewDidAppear() method at program start and comparing that data with a data file on disk. If an inconsistency is detected while loading during comparison, I want to give the user an option to continue loading the changed data, or exit the app and fix what needs to be fixed.
import Cocoa
class ViewController: NSViewController {
let utility = UtilityController()
let dataController = DataController() // <-- EDIT
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear() {
super.viewDidAppear() // <-- EDIT
dataController.fetchData() // <-- EDIT
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
import Cocoa
class UtilityController: NSObject {
func showAlert() {
let alert = NSAlert()
// Create an alert notification based upon what was discovered.
alert.messageText = "Warning: This is an alert!"
alert.informativeText = "Something informative will be here!"
alert.addButton(withTitle: "Continue")
alert.addButton(withTitle: "Exit")
if let mainViewWindow = NSApplication.shared.keyWindow?.contentViewController?.view.window {
alert.beginSheetModal(for: mainViewWindow) { (returnCode: NSApplication.ModalResponse) -> Void in
// Continue = 1000
// Exit = 1001
alert.window.close()
switch returnCode.rawValue {
case 1001: // Exit
exit(0)
default: // Continue
return
}
}
}
}
}
EDIT: I added this class, which I left out of the original post
import Cocoa
class DataController: NSObject {
// This is the controller class that performs CoreData CRUD
let utility = UtilityController()
func fetchData() {
// do the CoreData fetch of the data and if an error is found
utility.showAlert()
}
}
Upvotes: 1
Views: 441
Reputation: 236340
It would be much easier to extend NSViewController
and make showAlert
an instance method of it. This way you would have access to the view controller's view.window
property of the view controller which is calling this method. Note don't forget to call super
when overriding viewDidAppear
method. Note that your approach should work if you build and run your app (this is just an issue of running your app from Xcode) but be aware that your method might fail if your app is not active when executing that code. Using the view controller's view.window
property is much safer:
extension NSViewController {
func showAlert() {
let alert = NSAlert()
alert.messageText = "Warning: This is an alert!"
alert.informativeText = "Something informative will be here!"
alert.addButton(withTitle: "Continue")
alert.addButton(withTitle: "Exit")
if let window = view.window {
alert.beginSheetModal(for: window) { modalResponse in
alert.window.close()
switch modalResponse.rawValue {
case 1001: // Exit
exit(0)
default: // Continue
return
}
}
}
}
}
Usage:
class ViewController: NSViewController {
override func viewDidAppear() {
super.viewDidAppear()
showAlert()
}
}
edit/update:
If you don't want to extend NSViewController the safest approach is to pass the window when calling your method:
class ViewController: NSViewController {
let utility = UtilityController()
let dataController = DataController()
override func viewDidAppear() {
super.viewDidAppear()
dataController.fetchData(view.window)
}
}
class UtilityController: NSObject {
func showAlert(_ sender: NSWindow?) {
guard let sender = sender else { return }
let alert = NSAlert()
alert.messageText = "Warning: This is an alert!"
alert.informativeText = "Something informative will be here!"
alert.addButton(withTitle: "Continue")
alert.addButton(withTitle: "Exit")
alert.beginSheetModal(for: sender) { modalResponse in
alert.window.close()
switch modalResponse.rawValue {
case 1001:
exit(0)
default:
return
}
}
}
}
import Cocoa
class DataController: NSObject {
let utility = UtilityController()
func fetchData(_ sender: NSWindow?) {
utility.showAlert(sender)
}
}
Upvotes: 1