如何使用实用程序 class 中的 NSAlert Sheet 模式

How to use NSAlert Sheet Modal from a Utility class

我正在尝试在 UtilityController Class 中为 NSAlerts 编写一个方法,但该方法没有显示警报。我从我的 ViewController 中的 viewDidAppear() 方法调用它,所以我认为这会起作用,因为视图已经在屏幕上了。对吗?

我从 viewDidAppear() 方法调用它的原因是因为在我的实际应用程序中,我最初从 CoreData 加载数据,它在程序启动时从 viewDidAppear() 方法调用并将该数据与数据进行比较磁盘上的文件。如果在比较过程中加载时检测到不一致,我想给用户一个选择是继续加载更改的数据,还是退出应用程序并修复需要修复的内容。

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

编辑:我添加了这个 class,这是我在原来的 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()
    }
}

扩展 NSViewController 并使 showAlert 成为它的实例方法会容易得多。这样您就可以访问调用此方法的视图控制器的视图控制器的 view.window 属性 。注意不要忘记在覆盖 viewDidAppear 方法时调用 super 。请注意,如果您构建并 运行 您的应用程序(这只是从 Xcode 中 运行 宁您的应用程序的问题),您的方法应该有效,但请注意,如果您的应用程序可能会失败,则您的方法可能会失败执行该代码时未激活。使用视图控制器的 view.window 属性 更安全:

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

用法:

class ViewController: NSViewController {
    override func viewDidAppear() {
        super.viewDidAppear()
        showAlert()
    }
}

edit/update:

如果您不想扩展 NSViewController,最安全的方法是在调用您的方法时传递 window:

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