Странное поведение вспомогательного представления NSOpenPanel в расширении приложения Safari - PullRequest
1 голос
/ 14 января 2020

Я пишу всплывающее окно настроек для расширения приложения Safari. Он состоит из табличного представления с сегментированным элементом управления, содержащим шаблоны Add, Remove и Action. Последний показывает меню с элементами для импорта и экспорта настроек.

Импорт осуществляется через NSOpenPanel, к которому я добавил вспомогательное представление с флажком для замены существующих настроек вместо добавления к ним.

Проблема в том, что при выборе пункта меню вспомогательный вид оказывается позади модального NSOpenPanel, вызывая следующие действия.

  • На экране кратко появляется NSView перед NSOpenPanel,
  • NSOpenPanel показывает пустое пространство (правильного размера), где должно быть вспомогательное представление, и
  • Если вы нажмете на другое приложение (или рабочий стол), чтобы поставить Safari, уходит в фон, тогда вспомогательное представление появляется в NSOpenPanel, за исключением
  • Если другое приложение перекрывает NSOpenPanel, то над этим приложением появляется NSView, и вы можете нажать на флажок, чтобы изменить его, затем
  • При нажатии на Safari, чтобы сделать его впереди, NSView снова исчезает, однако
  • Нажатие кнопки Параметры n дважды из NSOpenPanel, чтобы закрыть вспомогательный вид, а затем снова открыть, чтобы устранить проблему.

Я добавил цвет фона к NSView, чтобы убедиться, что проблема именно с этим, а не с приложением NSButton.

Чтобы убедиться, что мой код был верным, я создал новый проект приложения с помощью всего одной кнопки в его представлении, а затем скопировал мой код в его окно действий. Он работал правильно.

Затем я создал новый проект расширения приложения Safari, сделал то же самое с его поповером и столкнулся с той же проблемой. Я также попытался переместить код за пределы контроллера представления для поповера, но это не имело никакого значения. Так что, похоже, проблема связана с тем, что он вызывается из расширения приложения Safari.

Кроме того, я предполагаю, что это связанная проблема, иногда, когда закрывается NSOpenPanel (либо путем выбора файла, либо отмены). это) управление не передается обратно в главное окно Safari. Это просто перестает отвечать. Вы можете перемещать окно по экрану, но само приложение, в том числе строка меню, не будет реагировать ни на какие действия мыши или клавиатуры. Единственный вариант - принудительно выйти из него. Однако это также влияет на NSSavePanel для экспорта, который не имеет дополнительного представления.

Я использую Xcode 11.3 на macOS 10.14.6 для Safari 13.0.4. Это код:

    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, а не использовать приложение для управления ими.

...