【问题标题】:NSOpenPanel, NSSavePanel runModal dismisses immediately with cancel, but only on M1 running 11.4NSOpenPanel, NSSavePanel runModal 立即取消取消,但仅在运行 11.4 的 M1 上
【发布时间】: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


【解决方案1】:

我可以在 MacOS X 12.3 的基于 SwiftUI 的实用程序中使用 OS X 12.3.1 和 Xcode 13.3.1 在 M1 iMac 上复制此行为。

该问题尚未得到纠正。其他开发人员建议我改用 FileDocument 和 DocumentGroup 协议。没有人可以解释 NSOpenPanel 在 SwiftUI 视图中调用时立即取消的这种异常行为。

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-02
  • 2019-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多