从 SwiftUI 中的 fileImporter 修改器更新进度值 [英] Update progress value from fileImporter modifier in SwiftUI

查看:76
本文介绍了从 SwiftUI 中的 fileImporter 修改器更新进度值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个进度条,它的值在使用 fileImporter 修饰符处理文件时更新.我不确定为什么在处理文件时进度条没有更新(是否因为它是关闭的一部分?).下面是我如何实现进度条.非常感谢任何帮助!

I have a progress bar with its value updated while processing a file using the fileImporter modifier. I am not sure why the progress bar is not updated as the file is being processed (is it because it is part of the closure?). Below is how I am implementing the progress bar. Any help is greatly appreciated!

ContentView 基本上有一个按钮,它使用一个按钮和一个闭包中的 .fileImporter 修饰符来触发对所选文件的处理.

the ContentView basically has a button that triggers the processing of the selected file using a button and the .fileImporter modifier in a closure.

struct ContentView: View {
@ObservedObject var progress = ProgressItem()
@State var importData: Bool = false

var body: some View {
    VStack {
        Button(action: {importData = true}, label: {Text("Import Data")})
            .fileImporter(isPresented: $importData, allowedContentTypes: [UTType.plainText], allowsMultipleSelection: false) { result in
                do {
                    guard let selectedFile: URL = try result.get().first else { return }
                    let secured = selectedFile.startAccessingSecurityScopedResource()
                    
                    DataManager().importData(fileURL: selectedFile)
                    if secured {selectedFile.stopAccessingSecurityScopedResource()}
                } catch {
                    print(error.localizedDescription)
                }
            }
        ProgressBar(value: $progress.progress).frame(height: 20)
    }
}

}

ProgressBar 是一个简单的视图,它获取进度值并更新它

The ProgressBar is a simple view that takes the progress value and updates it

struct ProgressBar: View {
@Binding var value: Double

var body: some View {
    GeometryReader { geometry in
        ZStack(alignment: .leading) {
            Rectangle().frame(width: geometry.size.width , height: geometry.size.height)
                .opacity(0.3)
                .foregroundColor(Color(UIColor.systemTeal))
            
            Rectangle().frame(width: min(CGFloat(self.value)*geometry.size.width, geometry.size.width), height: geometry.size.height)
                .foregroundColor(Color(UIColor.systemBlue))
                .animation(.linear)
            Text("\(value)")
        }.cornerRadius(45.0)
    }
}

}

我有一个 ProgressItem 类,它是一个包含进度值的 ObservableObject:

I have a ProgressItem class which is an ObservableObject that contains the progress value:

class ProgressItem: ObservableObject {
    @Published var progress: Double = 0
    @Published var message: String = ""
}

该文件作为 DataManager 类的一部分进行处理.为了这个问题,我已经去掉了处理细节,只用了一个print语句来打印每一行.下面是更新ProgressValue的DataManager类

The file is processed as part of the DataManager class. For the sake of this question, I have stripped out the processing details and just have a print statement to print out each line.Below is the DataManager class that updates the ProgressValue

class DataManager {
    @Published var progressBar: ProgressItem? = nil
    
    init() {
        progressBar = ProgressItem()
    }
    
    func importData(fileURL: URL, delimeter: String = ",") {
        let lines = try! String(contentsOf: fileURL, encoding: .utf8).components(separatedBy: .newlines).filter({!$0.isEmpty})
        let numlines = lines.count
        for index in 0..<numlines {
            let line = String(lines[index])
            print("\(line)")
            progressBar?.progress = Double(index)/Double(numlines) * 100
        }
    }
}

推荐答案

我会通过构造函数在 DataManager 中注入进度项

I'd inject progress item in DataManager via constructor

class DataManager {
    private var progressBar: ProgressItem? = nil
    
    init(progressBar: ProgressItem? = nil) {
        self.progressBar = progressBar
    }

    func importData(fileURL: URL, delimeter: String = ",") {

        // ... other code

        // if importing on background queue
        //DispatchQueue.main.async { // this better update async on main queue
            progressBar?.progress = Double(index)/Double(numlines) * 100
        //}
    }

然后将观察到的项目从视图注入DataManager,如

and then inject observed item from view into DataManager, like

    // ... other code

    DataManager(progressBar: self.progress).importData(fileURL: selectedFile)

    // ... other code

当然在某个地方/某个时候您需要重置当前的进度项目.我在你的代码中没有看到任何完成,但如果你有一个,它可能在里面.

of course somewhere/somewhen you need to reset your current progress item. I don't see any completion in your code, but if you have one it might be inside it.

这篇关于从 SwiftUI 中的 fileImporter 修改器更新进度值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆