在 SwiftUI 中导出文件时显示 ProgressView

Posted

技术标签:

【中文标题】在 SwiftUI 中导出文件时显示 ProgressView【英文标题】:Show ProgressView when Exporting File in SwiftUI 【发布时间】:2021-10-13 12:41:25 【问题描述】:

我在尝试导出文件时尝试显示 ProgressView。该文件是一个大文件,我正在使用fileExporter 修饰符。在 ZStack 中拥有 ProgressView 并将 zIndex 设置为 1 不起作用。我还尝试将长操作(获取文档)放入 DispatchQueue 但挑战在于它不是视图并且无法编译。以下是我目前拥有的代码。

这是我所期待的: 在我按下“导出文件”按钮后,我应该在创建文档时看到一个旋转的圆圈(在本例中是模拟长时间操作的 2 秒睡眠命令)。 之后应该显示来自 fileExporter 的“移动”表

非常感谢任何帮助。

这是一个示例应用程序:

struct ContentView: View 
    @State private var isExporting: Bool = false

    var body: some View 
        VStack 
            Button(action: 
                isExporting = true
            , label: 
                Text("Export File")
            )
                .padding()
            if isExporting 
                ProgressView() 
                    ZStack
                    .fileExporter(isPresented: $isExporting, document: FileExport(contents: "This is a simple Text"), contentType: .plainText)  result in
                        if case .success = result 
                            print(try! result.get())
                            print("File Saved")
                         else 
                            print("File Not Saved")
                        
                    
                
            
        
    


struct FileExport: FileDocument 
    static var readableContentTypes: [UTType] [.plainText]
    
    var contents: String
    
    init(contents: String) 
        self.contents = contents
        sleep(2) // simulate a long operation
    
    
    init(configuration: ReadConfiguration) throws 
        contents = ""
    
    
    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper 
        return FileWrapper(regularFileWithContents: contents.data(using: .utf8)!)
    

【问题讨论】:

什么是UTType?我的 xcode 说在范围内找不到类型“UTType”!你的xcode版本是什么?我应该导入一些东西吗? @swiftPunk UTTypeUniformTypeIdentifiers 包的一部分:import UniformTypeIdentifiers 【参考方案1】:

您的代码中存在一些问题。首先,您的ProgressView() 实际上并不包含在ZStack 中。您显示的唯一ZStack 不包含任何内容,因为内容必须在花括号内。在这种情况下,您通常可以将整个视图包裹在 ZStack 中。

接下来,您自己的视图通常不会采用这样的尾随闭包。您没有包含 ProgressView 代码,但是您显示的代码作为尾随闭包是荒谬的,所以我认为这不是您的意图。因此,我将打开的大括号移除为适当的关闭大括号。

说完所有这些后,视图将显示,但仍位于文件导出窗口下方。我从来没有找到任何将视图放置在这样的操作系统表上方的方法。如果是您的工作表,我已经看到了一些“解决方案”,但它们并不是真正推荐的。

此外,我不确定您如何获取数据以显示进度视图,而不仅仅是作为一个连续的微调器。我在文档中找不到 Apple 允许您访问该数据的任何地方。

最后,因为您将进度视图键入isPresented var isExporting 意味着您的ProgressView() 将在FileExport 表执行时关闭。

此外,虽然它似乎与条件 if 块内的 .fileExporter 一起使用,但我感觉不对,我会将其移至视图的另一部分。这似乎是一种不好的做法。

FWIW,这里是“工作”代码,但我看不出你如何才能真正实现你的目标:

struct FileExporter: View 
    @State private var isExporting: Bool = false
    
    var body: some View 
        ZStack 
            VStack 
                Button(action: 
                    isExporting = true
                , label: 
                    Text("Export File")
                )
                    .padding()
                
                if isExporting 
                    ProgressView() //  No brace would go here
                        .fileExporter(isPresented: $isExporting, document: FileExport(contents: "This is a simple Text"), contentType: .plainText)  result in
                            if case .success = result 
                                print(try! result.get())
                                print("File Saved")
                             else 
                                print("File Not Saved")
                            
                        
                
            
        
    

如果您想实现一个显示进度视图(条形图或微调器)的解决方案,我认为您必须自己动手。

【讨论】:

感谢您的建议。但是,这并不能解决问题!我希望在 fileExporter 呈现“移动”表之前创建文档之前看到一个旋转的圆圈 你希望在哪里看到旋转的圆圈? 我希望它会在“移动”屏幕出现之前显示在“导出文件”的顶部。 这是我认为你做不到的。据我了解,像这样的 Apple 工作表是系统工作表,因此它们存在于您的应用程序之外。因此,您不能在它们上放置ZStack.overlay 并在顶部放置视图。而且,它也将在您的应用之外进行处理。【参考方案2】:

这是一个可能的解决方案。可能有更好的方法来做到这一点!我正在使用ZStack 附加fileExporter。有没有不同的方法或其他解决方案?

struct ContentView: View 

    @State private var isExporting: Bool = false
    @State private var isLoading: Bool = false
    @State private var document: FileExport? = nil
    
    var body: some View 
        VStack 
            Button(action: 
                isExporting = true
                isLoading = true
                DispatchQueue.global(qos: .background).async 
                    document = FileExport(contents: "This is a simple text")
                    
                    DispatchQueue.main.async 
                        isLoading = false
                    
                
            , label: 
                Text("Export File")
            )
                .padding()
            
            if isLoading 
                ProgressView()
                    .zIndex(1.0)
            
            
            if isExporting && !isLoading 
                ZStack 
                    .fileExporter(isPresented: $isExporting, document: document, contentType: .plainText)  result in
                        if case .success = result 
                            print(try! result.get())
                            print("File Saved")
                         else 
                            print("File Not Saved")
                        
                    
            
        
    

【讨论】:

以上是关于在 SwiftUI 中导出文件时显示 ProgressView的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:在用户滑动以关闭时显示警报

如何在启动时显示 NavigationView (SwiftUI) 的详细视图

SwiftUI:如何在悬停时显示工具提示/提示?

仅在 iOS 14、SwiftUI 时显示一些视图

将 SwiftUI 警报或操作表绑定到值类型模型属性的可选性(当属性为 nil 时显示视图)的好方法是啥?

SwiftUI 中“触摸输入”的手势