【发布时间】:2022-04-25 01:32:02
【问题描述】:
我有一位用户报告说“打开”和“保存”面板已“自动关闭”。即打开面板对话框出现然后立即自行关闭,通过代码采用“取消”路径
文件打开菜单项是Storyboard中标准的firstResponder openDocument IBAction
AppDelegate 中有一个 IBAction openDocument 例程,它发布一个由主 ViewController 观察的通知,它创建 NSOpenPanel 并使用 RunModal 显示它
class AppDelegate: NSObject, NSApplicationDelegate {
// standard AppDelegate routines omitted for brevity
@IBAction func openDocument(_ sender: NSMenuItem) {
let nc = NotificationCenter.default
nc.post(Notification(name: Notification.Name("documentOpenRequested"), object: object))
}
}
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(doOpenDocument), name: Notification.Name("documentOpenRequested"), object: nil)
}
@objc func doOpenDocument(_ notification: Notification) {
print ("doOpenDocument called on MainThread: \(Thread.current.isMainThread)")
var URLToOpen: URL?
if let selectedURL = notification.object as? URL {
URLToOpen = selectedURL
} else {
let openPanel = NSOpenPanel();
openPanel.allowsMultipleSelection = false;
openPanel.canChooseDirectories = false;
openPanel.canCreateDirectories = false;
openPanel.canChooseFiles = true;
openPanel.allowedFileTypes = ["sdf", "json", "txt"]
openPanel.allowsOtherFileTypes = true
let i = openPanel.runModal();
if i.rawValue == NSApplication.ModalResponse.OK.rawValue {
if let myURL = openPanel.url {
URLToOpen = myURL
NSDocumentController.shared.noteNewRecentDocumentURL(myURL)
}
} else {
print ("RunModal exited with response not OK")
}
}
guard let theURL = URLToOpen else {
// URL was bad or user aborted open request, either way just bail
return
}
}
预期的行为是 RunModal 显示 OpenDialog 并等待用户选择文件并点击 OK 或 Cancel,这就是我在我的机器上得到的。
但是在这个用户的机器上(运行 11.4 的 MacBook Pro 13" M1 2020),RunModal 立即退出,并选择打印“RunModal exited with response not OK”的路径。因此用户无法选择文件
我确实阅读了一些建议在主队列之外执行 NSOpenPanel 的内容可能会导致崩溃。 Willeke 的参考建议在这种情况下通知将发布在主队列上。我更新了示例以打印队列是否是主队列并在我的系统上打印
在 MainThread 上调用的 doOpenDocument:true
所以将 NSOpenPanel 粘贴在一个
DispatchQueue.main.async {
let openPanel = ...
}
似乎无法解决问题。
我无权访问可以复制错误的特定机器,从而使进一步调试变得困难。 “自动取消”行为似乎仅限于这个用户的机器,但配置很常见,我怀疑我会收到其他报告,即使它仅限于具有 M1 芯片等的特定配置
任何人都可以在这台机器或其他机器上复制这种行为,或者遇到任何其他原因导致这种“自动取消”发生吗? (系统设置、病毒检查器等)?
(已更新问题以给出预期的行为和发生的行为、进一步的调试信息、其他人的代码信息请求和建议)
【问题讨论】:
-
没有人知道问题出在哪里,因为您不知道如何管理通知观察者。我什至不知道你在什么类下编写代码。在我看来,您缺少右大括号。
-
不太清楚管理通知观察者是什么意思,我展示了位于 ViewController 的 viewDidLoad 中的 AddObserver。我进行了编辑以显示这一点,并且 doOpenDocument 旨在显示相关的 sn-p。我知道 doOpenDocument 正在被触发,因为保存面板正在出现并且它可以在其他机器上运行。
-
"我展示了位于 ViewController 的 viewDidLoad 中的 AddObserver" 最初,你没有。
-
您从何处、何时以及如何发布通知?观察者还在吗?
-
这能回答你的问题吗? Is NSNotificationCenter thread safe?
标签: swift macos nsopenpanel dispatch-queue nssavepanel