进度条 iOS 13

ProgressBar iOS 13

我尝试创建自己的 ProgressView 来支持 iOS 13,但由于某种原因它似乎不起作用。我试过 @State@Binding 和普通的 var progress: Progress,但它根本没有更新。

struct ProgressBar: View {
    @Binding var progress: Progress

    var body: some View {
        VStack(alignment: .leading) {
            Text("\(Int(progress.fractionCompleted))% completed")
            ZStack {
                RoundedRectangle(cornerRadius: 2)
                    .foregroundColor(Color(UIColor.systemGray5))
                    .frame(height: 4)
                GeometryReader { metrics in
                    RoundedRectangle(cornerRadius: 2)
                        .foregroundColor(.blue)
                        .frame(width: metrics.size.width * CGFloat(progress.fractionCompleted))
                }
            }.frame(height: 4)
            Text("\(progress.completedUnitCount) of \(progress.totalUnitCount)")
                .font(.footnote)
                .foregroundColor(.gray)
        }
    }
}

在我的内容视图中,我添加了 iOS 14 变体和 iOS 13 支持变体。它们看起来一样,但 iOS 13 变体没有任何改变。

struct ContentView: View {
    @State private var progress = Progress(totalUnitCount: 10)
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        VStack {
            ProgressBar(progress: $progress)
                .padding()
                .onReceive(timer) { timer in
                    progress.completedUnitCount += 1
                    if progress.isFinished {
                        self.timer.upstream.connect().cancel()
                        progress.totalUnitCount = 500
                    }
                }
            if #available(iOS 14, *) {
                ProgressView(progress)
                    .padding()
                    .onReceive(timer) { timer in
                        progress.completedUnitCount += 1
                        if progress.isFinished {
                            self.timer.upstream.connect().cancel()
                            progress.totalUnitCount = 500
                        }
                    }
            }
        }
    }
}

iOS 14 变体有效,但我的 iOS 13 实施失败。有人可以帮助我吗?

Progress 是一个 NSObject,它不是一个结构,所以 state 对它不起作用。您必须使用 KVO 来观察 Progress 的变化并重定向到 SwiftUI 视图的真实来源。

这是可能解决方案的简化演示。使用 Xcode 12.1 / iOS 14.1

测试

class ProgressBarViewModel: ObservableObject {
    @Published var fractionCompleted: Double
    let progress: Progress
    private var observer: NSKeyValueObservation!
    
    init(_ progress: Progress) {
        self.progress = progress
        self.fractionCompleted = progress.fractionCompleted
        observer = progress.observe(\.completedUnitCount) { [weak self] (sender, _) in
            self?.fractionCompleted = sender.fractionCompleted
        }
    }
}

struct ProgressBar: View {
    @ObservedObject private var vm: ProgressBarViewModel
    
    init(_ progress: Progress) {
        self.vm = ProgressBarViewModel(progress)
    }
    
    var body: some View {
        VStack(alignment: .leading) {
            Text("\(Int(vm.fractionCompleted * 100))% completed")
            ZStack {
                RoundedRectangle(cornerRadius: 2)
                    .foregroundColor(Color(UIColor.systemGray5))
                    .frame(height: 4)
                GeometryReader { metrics in
                    RoundedRectangle(cornerRadius: 2)
                        .foregroundColor(.blue)
                        .frame(width: metrics.size.width * CGFloat(vm.fractionCompleted))
                }
            }.frame(height: 4)
            Text("\(vm.progress.completedUnitCount) of \(vm.progress.totalUnitCount)")
                .font(.footnote)
                .foregroundColor(.gray)
        }
    }
}

并更新调用位置以使用相同的构造函数

struct ContentView: View {
    @State private var progress = Progress(totalUnitCount: 10)
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        VStack {
            ProgressBar(progress)      // << here !!

// ... other code

backup