【问题标题】:ProgressBar iOS 13进度条 iOS 13
【发布时间】:2021-01-18 17:53:05
【问题描述】:

我尝试创建自己的 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 实现失败。有人可以帮帮我吗?

【问题讨论】:

    标签: swift swiftui progress-bar combine


    【解决方案1】:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多