首页 > 解决方案 > Safari App Extension 中奇怪的 NSOpenPanel 附件视图行为

问题描述

我正在为 Safari 应用程序扩展编写设置弹出框。这包括一个表格视图,下面有一个分段控件,其中包含添加、删除和操作模板。后者显示一个菜单,其中包含用于导入和导出设置的项目。

导入是通过NSOpenPanel我添加了一个带有复选框的附件视图来替换现有设置而不是添加到它们。

The problem is, when the menu item is selected the accessory view appears to be behind the the modal NSOpenPanelcausing the following behaviours.

我在 中添加了背景颜色,NSView以确认问题出在那个而不是封闭的NSButton.

为了验证我的代码是否正确,我创建了一个新的应用程序项目,其视图上只有一个按钮,然后将我的代码复制到其操作插座中。它工作正常。

然后我创建了一个新的 Safari App Extension 项目,并在它的弹出窗口上做了同样的事情,并遇到了同样的问题。我还尝试将代码移到弹出窗口的视图控制器之外,但这没有任何区别。因此,问题似乎与从 Safari 应用程序扩展中调用它有关。

另外,我认为是一个相关的问题,有时当NSOpenPanel关闭时(无论是通过选择文件还是取消它)控件不会传递回主 Safari 窗口。它只是变得没有反应。您可以在屏幕上移动窗口,但应用程序本身(包括菜单栏)不会响应任何鼠标或键盘输入。唯一的选择是强制退出它。但是,这也会影响NSSavePanel没有附件视图的导出。

我在 macOS 10.14.6 上为 Safari 13.0.4 使用 Xcode 11.3。这是代码:

    var overwriteSettings: Bool = false

    @objc func importSettingsCheckBox(_ button: NSButton) {

        self.overwriteSettings = button.state == .on

    }

    @IBAction func importSettings(_ sender: Any) {

        let openFileDialog = NSOpenPanel()
        openFileDialog.title = "Choose a settings file…"
        openFileDialog.directoryURL = FileManager.default.homeDirectoryForCurrentUser
//        openFileDialog.allowedFileTypes = ["json"]
//        openFileDialog.allowsOtherFileTypes = true

        let dialogWidth = openFileDialog.frame.width

       let overwriteSettingsButton = NSButton()
        overwriteSettingsButton.setButtonType(.switch)
        overwriteSettingsButton.title = "Remove existing settings on import?"
        overwriteSettingsButton.target = self
        overwriteSettingsButton.action = #selector(importSettingsCheckBox(_:))
        overwriteSettingsButton.sizeToFit()

        let dialogWidth = openFileDialog.frame.width
        let buttonHeight = overwriteSettingsButton.frame.height

        overwriteSettingsButton.setFrameOrigin(NSMakePoint((dialogWidth - overwriteSettingsButton.frame.width) / 2, buttonHeight / 2))

        let accessoryView = NSView(frame: NSMakeRect(0, 0, dialogWidth, buttonHeight * 2))
        accessoryView.autoresizesSubviews = true
        accessoryView.addSubview(overwriteSettingsButton)

        openFileDialog.accessoryView = accessoryView
        openFileDialog.isAccessoryViewDisclosed = true

        if openFileDialog.runModal() == NSApplication.ModalResponse.OK {

            if let result = openFileDialog.url {
                NSLog("I want to open \(result.path), overwrite status: \(self.overwriteSettings)")
            }

        } else {

            NSLog("No file selected")

        }

        return

    }

(注释掉的行是因为NSOpenPanel.allowsOtherFileTypes被忽略了,但至少这在独立应用程序测试中也一直不起作用!)

谁能解释一下?我真的很想在 Safari 中进行设置,而不是使用包含的应用程序来管理它们。

标签: swiftnsopenpanelaccessoryviewsafari-app-extension

解决方案


推荐阅读