执行导出/导入菜单命令?

问题描述 投票:0回答:2

我有一个导入(和导出)按钮,可以很好地放置在视图中。

var body: some View {
    Button(action: {
        isImporting = true
    }, label: {
        Label("Import", systemImage: "square.and.arrow.down")
    })
    .fileImporter(
        isPresented: $isImporting,
        allowedContentTypes: [UTType.log, UTType.text, UTType.xml, UTType.zip],
        allowsMultipleSelection: true
    ) { result in
        switch result {
        case let .success(files):
            files.forEach { file in
                guard file.startAccessingSecurityScopedResource() else { return }
                    .../...
                file.stopAccessingSecurityScopedResource()
            }
        case let .failure(error):
            print(error)
        }
    }
}

但我还希望通过 macOS 应用程序中的“文件”菜单使用导入/导出命令。

struct ImportExportCommands: Commands {
    @MainActor
    var body: some Commands {
        CommandGroup(replacing: .importExport) {
            Section {
                ImportButton()
                    .modelContainer(mdContainer.sharedModelContainer)
                ExportButton()
                    .modelContainer(mdContainer.sharedModelContainer)
            }
        }
    }
}

执行了操作代码,但没有出现文件对话框。

我没有找到任何关于此的信息,所以我认为这是一件非常愚蠢的事情。

如何通过菜单命令在屏幕上弹出 fileImporter/fileExporter 对话框?

macos swiftui menuitem swift-data
2个回答
0
投票

我看到的问题是,您首先需要打开窗口才能使

.fileImporter
修改器起作用,但解决此问题的一种方法是使用
NSOpenPanel
代替。

类似这样的:

struct ImportExportCommands: Commands {
    @Environment(\.openWindow) private var openWindows
    @MainActor
    var body: some Commands {
        CommandGroup(replacing: .importExport) {
            Section {
                Button("Import") {
                    selectImportFiles()
                }
            }
        }
    }

    private func selectImportFiles() {
        let openPanel = NSOpenPanel()
        openPanel.title = "Import files"
        openPanel.prompt = "Import"
        openPanel.canChooseFiles = true
        openPanel.allowsMultipleSelection = true
        openPanel.allowedContentTypes = [UTType.log, UTType.text, UTType.xml, UTType.zip]

        openPanel.begin { result in
            if result == .OK {
                for fileUrl in openPanel.urls {
                    print(fileUrl.absoluteString)
                }
            }
        }
    }
}

0
投票

我在 SwiftUI 应用程序中遇到了类似的问题。对我有用的是向菜单视图添加聚焦绑定。

添加焦点绑定需要您执行以下操作:

  • 为焦点绑定创建焦点值键结构。
  • 为您创建的焦点值键创建 SwiftUI 的
    FocusedValues
    结构的扩展。
  • 向菜单视图添加聚焦绑定。
  • 在应用程序结构或更高级别的视图(例如内容视图)中设置聚焦场景值。

焦点值键结构必须符合

FocusedValueKey
协议。为重点值类型提供类型别名。以下代码为 SwiftUI 文档结构创建一个焦点值类型:

struct DocumentFocusedValueKey: FocusedValueKey {
    typealias Value = Binding<Document>
}

FocusedValues
扩展的计算属性要求您为您创建的焦点值键结构添加 getter 和 setter。

extension FocusedValues {
    var document: DocumentFocusedValueKey.Value? {
        get {
            return self[DocumentFocusedValueKey.self]
        }
        
        set {
            self[DocumentFocusedValueKey.self] = newValue
        }
    }
}

使用

@FocusedBinding
属性包装器将焦点绑定添加到菜单视图。

@FocusedBinding(\.document) var document: Document?

您在

@FocusedBinding
之后放置的值是您作为
FocusedValues
的扩展添加的计算属性的名称。

使用

.focusedSceneValue
修改器设置聚焦场景值。以下示例将聚焦场景的值设置为基于文档的应用程序中的文档:

.focusedSceneValue(\.document, file.$document)

在此示例中,您将在应用程序结构中设置

.focusedSceneValue
修饰符。

© www.soinside.com 2019 - 2024. All rights reserved.